Punt the rc_strcatpaths function and use snprintf instead to save on expensive malloc calls.
This commit is contained in:
@@ -31,6 +31,30 @@
|
||||
|
||||
#include "librc.h"
|
||||
|
||||
#ifdef __GLIBC__
|
||||
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
|
||||
static size_t strlcpy(char *dst, const char *src, size_t size)
|
||||
{
|
||||
const char *s = src;
|
||||
size_t n = size;
|
||||
|
||||
if (n && --n)
|
||||
do {
|
||||
if (! (*dst++ = *src++))
|
||||
break;
|
||||
} while (--n);
|
||||
|
||||
if (! n) {
|
||||
if (size)
|
||||
*dst = '\0';
|
||||
while (*src++);
|
||||
}
|
||||
|
||||
return src - s - 1;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
static bool pid_is_cmd(pid_t pid, const char *cmd)
|
||||
{
|
||||
@@ -289,12 +313,12 @@ 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[PATH_MAX];
|
||||
FILE *fp;
|
||||
RC_STRING *m;
|
||||
|
||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
||||
fp = fopen(ffile, "r");
|
||||
free(ffile);
|
||||
|
||||
if (! fp)
|
||||
return false;
|
||||
@@ -352,16 +376,15 @@ static RC_STRINGLIST *_match_list(const char* const* argv,
|
||||
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;
|
||||
char dirpath[PATH_MAX];
|
||||
char file[PATH_MAX];
|
||||
int nfiles = 0;
|
||||
char *oldfile = NULL;
|
||||
char oldfile[PATH_MAX] = { '\0' };
|
||||
bool retval = false;
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
RC_STRINGLIST *match;
|
||||
int i = 0;
|
||||
char buffer[10];
|
||||
FILE *fp;
|
||||
|
||||
if (!(argv && *argv) && ! name && ! pidfile) {
|
||||
@@ -369,40 +392,40 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
return false;
|
||||
}
|
||||
|
||||
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons",
|
||||
basename_c(service), (char *) NULL);
|
||||
|
||||
match = _match_list(argv, name, pidfile);
|
||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
|
||||
/* Regardless, erase any existing daemon info */
|
||||
if ((dp = opendir(dirpath))) {
|
||||
match = _match_list(argv, name, pidfile);
|
||||
while ((d = readdir(dp))) {
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
file = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
|
||||
|
||||
snprintf(file, sizeof(file), "%s/%s",
|
||||
dirpath, d->d_name);
|
||||
nfiles++;
|
||||
|
||||
if (! oldfile) {
|
||||
if (! *oldfile) {
|
||||
if (_match_daemon(dirpath, d->d_name, match)) {
|
||||
unlink (file);
|
||||
oldfile = file;
|
||||
unlink(file);
|
||||
strlcpy(oldfile, file, sizeof(oldfile));
|
||||
nfiles--;
|
||||
}
|
||||
} else {
|
||||
rename(file, oldfile);
|
||||
free(oldfile);
|
||||
oldfile = file;
|
||||
strlcpy(oldfile, file, sizeof(oldfile));
|
||||
}
|
||||
}
|
||||
free(file);
|
||||
closedir(dp);
|
||||
rc_stringlist_free(match);
|
||||
}
|
||||
|
||||
/* Now store our daemon info */
|
||||
if (started) {
|
||||
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
||||
snprintf(buffer, sizeof(buffer), "%03d", nfiles + 1);
|
||||
file = rc_strcatpaths(dirpath, buffer, (char *) NULL);
|
||||
snprintf(file, sizeof(file), "%s/%03d",
|
||||
dirpath, nfiles + 1);
|
||||
if ((fp = fopen(file, "w"))) {
|
||||
while (argv && argv[i]) {
|
||||
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
|
||||
@@ -418,25 +441,19 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
fclose(fp);
|
||||
retval = true;
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
} else
|
||||
retval = true;
|
||||
|
||||
rc_stringlist_free(match);
|
||||
free(dirpath);
|
||||
|
||||
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 dirpath[PATH_MAX];
|
||||
char file[16];
|
||||
RC_STRINGLIST *match;
|
||||
bool retval = false;
|
||||
DIR *dp;
|
||||
@@ -445,17 +462,13 @@ rc_service_started_daemon (const char *service, const char *const *argv,
|
||||
if (!service || !(argv && *argv))
|
||||
return false;
|
||||
|
||||
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
|
||||
(char *) NULL);
|
||||
|
||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
match = _match_list(argv, NULL, NULL);
|
||||
|
||||
if (indx > 0) {
|
||||
l = sizeof (char) * 10;
|
||||
file = xmalloc(l);
|
||||
snprintf(file, l, "%03d", indx);
|
||||
snprintf(file, sizeof(file), "%03d", indx);
|
||||
retval = _match_daemon(dirpath, file, match);
|
||||
free(file);
|
||||
} else {
|
||||
if ((dp = opendir(dirpath))) {
|
||||
while ((d = readdir(dp))) {
|
||||
@@ -469,7 +482,6 @@ rc_service_started_daemon (const char *service, const char *const *argv,
|
||||
}
|
||||
}
|
||||
|
||||
free(dirpath);
|
||||
rc_stringlist_free(match);
|
||||
return retval;
|
||||
}
|
||||
@@ -477,10 +489,10 @@ librc_hidden_def(rc_service_started_daemon)
|
||||
|
||||
bool rc_service_daemons_crashed(const char *service)
|
||||
{
|
||||
char *dirpath;
|
||||
char dirpath[PATH_MAX];
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
char *path;
|
||||
char *path = dirpath;
|
||||
FILE *fp;
|
||||
char *line;
|
||||
char **argv = NULL;
|
||||
@@ -498,21 +510,19 @@ bool rc_service_daemons_crashed(const char *service)
|
||||
RC_STRING *s;
|
||||
size_t i;
|
||||
|
||||
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
|
||||
(char *) NULL);
|
||||
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
|
||||
if (! (dp = opendir(dirpath))) {
|
||||
free(dirpath);
|
||||
if (! (dp = opendir(dirpath)))
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
||||
d->d_name);
|
||||
fp = fopen(dirpath, "r");
|
||||
if (! fp)
|
||||
break;
|
||||
|
||||
|
||||
@@ -360,12 +360,12 @@ static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
||||
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)
|
||||
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;
|
||||
@@ -392,7 +392,9 @@ static void visit_service (const RC_DEPTREE *deptree,
|
||||
if (! options & RC_DEP_TRACE ||
|
||||
strcmp(type->value, "iprovide") == 0)
|
||||
{
|
||||
rc_stringlist_add(sorted, service->value);
|
||||
if (! *sorted)
|
||||
*sorted = rc_stringlist_new();
|
||||
rc_stringlist_add(*sorted, service->value);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -445,8 +447,11 @@ static void visit_service (const RC_DEPTREE *deptree,
|
||||
are also the service calling us or we are provided by something */
|
||||
svcname = getenv("SVCNAME");
|
||||
if (! svcname || strcmp(svcname, depinfo->service) != 0)
|
||||
if (! get_deptype(depinfo, "providedby"))
|
||||
rc_stringlist_add(sorted, depinfo->service);
|
||||
if (! get_deptype(depinfo, "providedby")) {
|
||||
if (! *sorted)
|
||||
*sorted = rc_stringlist_new();
|
||||
rc_stringlist_add(*sorted, depinfo->service);
|
||||
}
|
||||
}
|
||||
|
||||
RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||
@@ -478,7 +483,7 @@ RC_STRINGLIST *rc_deptree_depends (const RC_DEPTREE *deptree,
|
||||
const RC_STRINGLIST *services,
|
||||
const char *runlevel, int options)
|
||||
{
|
||||
RC_STRINGLIST *sorted = rc_stringlist_new();
|
||||
RC_STRINGLIST *sorted = NULL;
|
||||
RC_STRINGLIST *visited = rc_stringlist_new();
|
||||
RC_DEPINFO *di;
|
||||
const RC_STRING *service;
|
||||
@@ -493,11 +498,11 @@ RC_STRINGLIST *rc_deptree_depends (const RC_DEPTREE *deptree,
|
||||
continue;
|
||||
}
|
||||
if (types)
|
||||
visit_service (deptree, types, sorted, visited,
|
||||
di, runlevel, options);
|
||||
visit_service(deptree, types, &sorted, visited,
|
||||
di, runlevel, options);
|
||||
}
|
||||
|
||||
rc_stringlist_free (visited);
|
||||
rc_stringlist_free(visited);
|
||||
return sorted;
|
||||
}
|
||||
librc_hidden_def(rc_deptree_depends)
|
||||
@@ -522,12 +527,23 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
||||
list = rc_services_in_state(RC_SERVICE_STARTED);
|
||||
|
||||
list2 = rc_services_in_state (RC_SERVICE_INACTIVE);
|
||||
TAILQ_CONCAT(list, list2, entries);
|
||||
free(list2);
|
||||
if (list2) {
|
||||
if (list) {
|
||||
TAILQ_CONCAT(list, list2, entries);
|
||||
free(list2);
|
||||
} else
|
||||
list = list2;
|
||||
}
|
||||
|
||||
list2 = rc_services_in_state (RC_SERVICE_STARTING);
|
||||
if (list2) {
|
||||
if (list) {
|
||||
TAILQ_CONCAT(list, list2, entries);
|
||||
free(list2);
|
||||
} else
|
||||
list = list2;
|
||||
}
|
||||
TAILQ_CONCAT(list, list2, entries);
|
||||
free(list2);
|
||||
} else {
|
||||
list = rc_services_in_runlevel (runlevel);
|
||||
|
||||
@@ -567,7 +583,7 @@ bool rc_newer_than(const char *source, const char *target)
|
||||
bool newer = true;
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
char *path;
|
||||
char path[PATH_MAX];
|
||||
int serrno = errno;
|
||||
|
||||
/* We have to exist */
|
||||
@@ -594,9 +610,8 @@ bool rc_newer_than(const char *source, const char *target)
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
path = rc_strcatpaths(target, d->d_name, (char *) NULL);
|
||||
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
|
||||
newer = rc_newer_than(source, path);
|
||||
free(path);
|
||||
if (! newer)
|
||||
break;
|
||||
}
|
||||
@@ -671,14 +686,16 @@ bool rc_deptree_update_needed(void)
|
||||
|
||||
/* 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)) {
|
||||
newer = true;
|
||||
break;
|
||||
config = rc_config_list(RC_DEPCONFIG);
|
||||
if (config) {
|
||||
TAILQ_FOREACH(s, config, entries) {
|
||||
if (! rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
|
||||
newer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc_stringlist_free(config);
|
||||
}
|
||||
rc_stringlist_free(config);
|
||||
|
||||
return newer;
|
||||
}
|
||||
|
||||
@@ -54,57 +54,6 @@ bool rc_yesno (const char *value)
|
||||
}
|
||||
librc_hidden_def(rc_yesno)
|
||||
|
||||
char *rc_strcatpaths (const char *path1, const char *paths, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t length;
|
||||
size_t i;
|
||||
char *p;
|
||||
char *path;
|
||||
char *pathp;
|
||||
|
||||
if (! path1 || ! paths)
|
||||
return NULL;
|
||||
|
||||
length = strlen (path1) + strlen (paths) + 1;
|
||||
if (*paths != '/')
|
||||
length ++;
|
||||
|
||||
va_start (ap, paths);
|
||||
while ((p = va_arg (ap, char *)) != NULL) {
|
||||
if (*p != '/')
|
||||
length ++;
|
||||
length += strlen (p);
|
||||
}
|
||||
va_end (ap);
|
||||
|
||||
pathp = path = xmalloc (length * sizeof (char));
|
||||
memset (path, 0, length);
|
||||
i = strlen (path1);
|
||||
memcpy (path, path1, i);
|
||||
pathp += i;
|
||||
if (*paths != '/')
|
||||
*pathp ++ = '/';
|
||||
i = strlen (paths);
|
||||
memcpy (pathp, paths, i);
|
||||
pathp += i;
|
||||
|
||||
va_start (ap, paths);
|
||||
while ((p = va_arg (ap, char *)) != NULL) {
|
||||
if (*p != '/')
|
||||
*pathp ++= '/';
|
||||
i = strlen (p);
|
||||
memcpy (pathp, p, i);
|
||||
pathp += i;
|
||||
}
|
||||
va_end (ap);
|
||||
|
||||
*pathp++ = 0;
|
||||
|
||||
return path;
|
||||
}
|
||||
librc_hidden_def(rc_strcatpaths)
|
||||
|
||||
char *rc_getline (FILE *fp)
|
||||
{
|
||||
char *line = NULL;
|
||||
@@ -138,13 +87,11 @@ RC_STRINGLIST *rc_config_list(const char *file)
|
||||
char *buffer;
|
||||
char *p;
|
||||
char *token;
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRINGLIST *list = NULL;
|
||||
|
||||
if (!(fp = fopen(file, "r")))
|
||||
return NULL;
|
||||
|
||||
list = rc_stringlist_new();
|
||||
|
||||
while ((p = buffer = rc_getline(fp))) {
|
||||
/* Strip leading spaces/tabs */
|
||||
while ((*p == ' ') || (*p == '\t'))
|
||||
@@ -159,6 +106,8 @@ RC_STRINGLIST *rc_config_list(const char *file)
|
||||
if (token[strlen(token) - 1] == '\n')
|
||||
token[strlen(token) - 1] = 0;
|
||||
|
||||
if (! list)
|
||||
list = rc_stringlist_new();
|
||||
rc_stringlist_add(list, token);
|
||||
}
|
||||
}
|
||||
@@ -172,8 +121,8 @@ librc_hidden_def(rc_config_list)
|
||||
|
||||
RC_STRINGLIST *rc_config_load(const char *file)
|
||||
{
|
||||
RC_STRINGLIST *list = NULL;
|
||||
RC_STRINGLIST *config = NULL;
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRINGLIST *config;
|
||||
char *token;
|
||||
RC_STRING *line;
|
||||
RC_STRING *cline;
|
||||
@@ -183,9 +132,11 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
||||
char *newline;
|
||||
char *p;
|
||||
|
||||
config = rc_stringlist_new();
|
||||
|
||||
list = rc_config_list(file);
|
||||
if (! list)
|
||||
return NULL;
|
||||
|
||||
config = rc_stringlist_new();
|
||||
TAILQ_FOREACH(line, list, entries) {
|
||||
/* Get entry */
|
||||
p = line->value;
|
||||
|
||||
@@ -62,7 +62,7 @@ RC_STRING *rc_stringlist_addu (RC_STRINGLIST *list, const char *value)
|
||||
}
|
||||
librc_hidden_def(rc_stringlist_addu)
|
||||
|
||||
bool rc_stringlist_delete (RC_STRINGLIST *list, const char *value)
|
||||
bool rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
|
||||
{
|
||||
RC_STRING *s;
|
||||
|
||||
|
||||
@@ -72,25 +72,24 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRINGLIST *list = NULL;
|
||||
struct stat buf;
|
||||
size_t l;
|
||||
char *file;
|
||||
char file[PATH_MAX];
|
||||
int r;
|
||||
|
||||
if ((dp = opendir(dir)) == NULL)
|
||||
return NULL;
|
||||
|
||||
list = rc_stringlist_new();
|
||||
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 also have been removed. */
|
||||
file = rc_strcatpaths(dir, d->d_name, NULL);
|
||||
snprintf(file, sizeof(file), "%s/%s",
|
||||
dir, d->d_name);
|
||||
r = stat(file, &buf);
|
||||
free(file);
|
||||
if (r != 0)
|
||||
continue;
|
||||
|
||||
@@ -106,6 +105,8 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)
|
||||
! S_ISDIR(buf.st_mode))
|
||||
continue;
|
||||
}
|
||||
if (! list)
|
||||
list = rc_stringlist_new();
|
||||
rc_stringlist_add(list, d->d_name);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +119,7 @@ static bool rm_dir(const char *pathname, bool top)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
char *tmp = NULL;
|
||||
char file[PATH_MAX];
|
||||
struct stat s;
|
||||
bool retval = true;
|
||||
|
||||
@@ -128,22 +129,21 @@ static bool rm_dir(const char *pathname, bool top)
|
||||
errno = 0;
|
||||
while (((d = readdir(dp)) != NULL) && errno == 0) {
|
||||
if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
|
||||
free(tmp);
|
||||
tmp = rc_strcatpaths(pathname, d->d_name, (char *) NULL);
|
||||
snprintf(file, sizeof(file), "%s/%s", pathname, d->d_name);
|
||||
|
||||
if (stat(tmp, &s) != 0) {
|
||||
if (stat(file, &s) != 0) {
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR(s.st_mode)) {
|
||||
if (! rm_dir(tmp, true))
|
||||
if (! rm_dir(file, true))
|
||||
{
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (unlink(tmp)) {
|
||||
if (unlink(file)) {
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
@@ -151,7 +151,6 @@ static bool rm_dir(const char *pathname, bool top)
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
free(tmp);
|
||||
|
||||
if (! retval)
|
||||
return false;
|
||||
@@ -302,18 +301,16 @@ librc_hidden_def(rc_runlevel_set)
|
||||
|
||||
bool rc_runlevel_exists(const char *runlevel)
|
||||
{
|
||||
char *path;
|
||||
char path[PATH_MAX];
|
||||
struct stat buf;
|
||||
bool retval = false;
|
||||
|
||||
if (! runlevel)
|
||||
return false;
|
||||
|
||||
path = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL);
|
||||
snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
|
||||
if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
|
||||
retval = true;
|
||||
free(path);
|
||||
return retval;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
librc_hidden_def(rc_runlevel_exists)
|
||||
|
||||
@@ -321,8 +318,8 @@ librc_hidden_def(rc_runlevel_exists)
|
||||
char *rc_service_resolve(const char *service)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
char *file;
|
||||
int r = 0;
|
||||
char file[PATH_MAX];
|
||||
int r;
|
||||
struct stat buf;
|
||||
|
||||
if (! service)
|
||||
@@ -332,43 +329,41 @@ char *rc_service_resolve(const char *service)
|
||||
return xstrdup(service);
|
||||
|
||||
/* First check started services */
|
||||
file = rc_strcatpaths(RC_SVCDIR, "started", service, (char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", "started", service);
|
||||
if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
|
||||
free(file);
|
||||
file = rc_strcatpaths(RC_SVCDIR, "inactive", service, (char *) NULL);
|
||||
if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
|
||||
free(file);
|
||||
file = NULL;
|
||||
}
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||
"inactive", service);
|
||||
if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode))
|
||||
*file = '\0';
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
/* Nope, so lets see if the user has written it */
|
||||
#ifdef RC_LOCAL_INITDIR
|
||||
snprintf(buffer, sizeof(buffer), RC_LOCAL_INITDIR "/%s", service);
|
||||
if (stat(buffer, &buf) == 0)
|
||||
return xstrdup(buffer);
|
||||
#endif
|
||||
|
||||
if (file) {
|
||||
if (*file) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
r = readlink(file, buffer, sizeof(buffer));
|
||||
free(file);
|
||||
if (r > 0)
|
||||
return xstrdup(buffer);
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), RC_INITDIR "/%s", service);
|
||||
|
||||
/* So we don't exist in /etc/init.d - check RC_PKG_INITDIR */
|
||||
#ifdef RC_PKG_INITDIR
|
||||
if (stat(buffer, &buf) != 0) {
|
||||
snprintf(buffer, sizeof(buffer), RC_PKG_INITDIR "/%s", service);
|
||||
if (stat(buffer, &buf) != 0)
|
||||
return NULL;
|
||||
}
|
||||
#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
|
||||
|
||||
return xstrdup(buffer);
|
||||
/* 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)
|
||||
|
||||
@@ -406,7 +401,7 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
||||
char *svc;
|
||||
char *cmd = NULL;
|
||||
char *buffer = NULL;
|
||||
RC_STRINGLIST *commands;
|
||||
RC_STRINGLIST *commands = NULL;
|
||||
char *token;
|
||||
char *p;
|
||||
FILE *fp;
|
||||
@@ -415,7 +410,6 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
||||
if (! (svc = rc_service_resolve(service)))
|
||||
return NULL;
|
||||
|
||||
commands = rc_stringlist_new();
|
||||
|
||||
l = strlen(OPTSTR) + strlen(svc) + 1;
|
||||
cmd = xmalloc(sizeof(char) * l);
|
||||
@@ -424,8 +418,11 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
||||
|
||||
if ((fp = popen(cmd, "r"))) {
|
||||
p = buffer = rc_getline(fp);
|
||||
while ((token = strsep(&p, " ")))
|
||||
while ((token = strsep(&p, " "))) {
|
||||
if (! commands)
|
||||
commands = rc_stringlist_new();
|
||||
rc_stringlist_add(commands, token);
|
||||
}
|
||||
pclose(fp);
|
||||
free(buffer);
|
||||
}
|
||||
@@ -464,24 +461,17 @@ librc_hidden_def(rc_service_description)
|
||||
|
||||
bool rc_service_in_runlevel(const char *service, const char *runlevel)
|
||||
{
|
||||
char *file;
|
||||
bool retval;
|
||||
char file[PATH_MAX];
|
||||
|
||||
if (! runlevel || ! service)
|
||||
return false;
|
||||
|
||||
file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service),
|
||||
(char *) NULL);
|
||||
retval = exists(file);
|
||||
free(file);
|
||||
|
||||
return retval;
|
||||
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;
|
||||
char file[PATH_MAX];
|
||||
int i = 0;
|
||||
int skip_state = -1;
|
||||
const char *base;
|
||||
@@ -504,18 +494,16 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)
|
||||
return false;
|
||||
}
|
||||
|
||||
file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state (state), base,
|
||||
(char *) NULL);
|
||||
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(file);
|
||||
free(init);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(file);
|
||||
skip_state = state;
|
||||
}
|
||||
|
||||
@@ -534,24 +522,22 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)
|
||||
s != RC_SERVICE_SCHEDULED) &&
|
||||
(! skip_wasinactive || s != RC_SERVICE_WASINACTIVE))
|
||||
{
|
||||
file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(s), base,
|
||||
(char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||
rc_parse_service_state(s), base);
|
||||
if (exists(file)) {
|
||||
if ((state == RC_SERVICE_STARTING ||
|
||||
state == RC_SERVICE_STOPPING) &&
|
||||
s == RC_SERVICE_INACTIVE)
|
||||
{
|
||||
was = rc_strcatpaths(RC_SVCDIR,
|
||||
rc_parse_service_state(RC_SERVICE_WASINACTIVE),
|
||||
base, (char *) NULL);
|
||||
|
||||
snprintf(was, sizeof(was),
|
||||
RC_SVCDIR "/%s/%s",
|
||||
rc_parse_service_state(RC_SERVICE_WASINACTIVE),
|
||||
base);
|
||||
symlink(init, was);
|
||||
skip_wasinactive = true;
|
||||
free(was);
|
||||
}
|
||||
unlink(file);
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,42 +546,43 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)
|
||||
state == RC_SERVICE_STOPPED ||
|
||||
state == RC_SERVICE_INACTIVE)
|
||||
{
|
||||
file = rc_strcatpaths(RC_SVCDIR, "exclusive", base, (char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||
"exclusive", base);
|
||||
unlink(file);
|
||||
free(file);
|
||||
}
|
||||
|
||||
/* Remove any options and daemons the service may have stored */
|
||||
if (state == RC_SERVICE_STOPPED) {
|
||||
file = rc_strcatpaths(RC_SVCDIR, "options", base, (char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||
"options", base);
|
||||
rm_dir(file, true);
|
||||
free(file);
|
||||
|
||||
file = rc_strcatpaths(RC_SVCDIR, "daemons", base, (char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||
"daemons", base);
|
||||
rm_dir(file, true);
|
||||
free(file);
|
||||
|
||||
rc_service_schedule_clear(service);
|
||||
}
|
||||
|
||||
/* These are final states, so remove us from scheduled */
|
||||
if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
|
||||
file = rc_strcatpaths(RC_SVCDIR, "scheduled", (char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");
|
||||
dirs = ls_dir(file, 0);
|
||||
if (dirs) {
|
||||
TAILQ_FOREACH(dir, dirs, entries) {
|
||||
snprintf(was, sizeof(was), "%s/%s/%s",
|
||||
file, dir->value, base);
|
||||
unlink(was);
|
||||
|
||||
TAILQ_FOREACH(dir, dirs, entries) {
|
||||
was = rc_strcatpaths(file, dir->value, base, (char *) NULL);
|
||||
unlink(was);
|
||||
free(was);
|
||||
|
||||
/* Try and remove the dir - we don't care about errors */
|
||||
was = rc_strcatpaths(file, dir->value, (char *) NULL);
|
||||
serrno = errno;
|
||||
rmdir(was);
|
||||
errno = serrno;
|
||||
free(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);
|
||||
}
|
||||
rc_stringlist_free(dirs);
|
||||
}
|
||||
|
||||
free(init);
|
||||
@@ -607,35 +594,36 @@ RC_SERVICE rc_service_state(const char *service)
|
||||
{
|
||||
int i;
|
||||
int state = RC_SERVICE_STOPPED;
|
||||
char *file;
|
||||
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++) {
|
||||
file = rc_strcatpaths(RC_SVCDIR, rc_service_state_names[i].name,
|
||||
basename_c(service), (char*) NULL);
|
||||
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;
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
|
||||
if (state & RC_SERVICE_STOPPED) {
|
||||
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||
TAILQ_FOREACH (dir, dirs, entries) {
|
||||
file = rc_strcatpaths(RC_SVCDIR, "scheduled",
|
||||
dir->value,
|
||||
service, (char *) NULL);
|
||||
if (exists(file))
|
||||
state |= RC_SERVICE_SCHEDULED;
|
||||
free(file);
|
||||
if (state & RC_SERVICE_SCHEDULED)
|
||||
break;
|
||||
if (dirs) {
|
||||
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);
|
||||
}
|
||||
rc_stringlist_free(dirs);
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -646,14 +634,14 @@ char *rc_service_value_get(const char *service, const char *option)
|
||||
{
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
char *file = rc_strcatpaths(RC_SVCDIR, "options", service, option,
|
||||
(char *) NULL);
|
||||
char file[PATH_MAX];
|
||||
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
|
||||
service, option);
|
||||
if ((fp = fopen(file, "r"))) {
|
||||
line = rc_getline(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
free(file);
|
||||
|
||||
return line;
|
||||
}
|
||||
@@ -663,33 +651,27 @@ bool rc_service_value_set(const char *service, const char *option,
|
||||
const char *value)
|
||||
{
|
||||
FILE *fp;
|
||||
char *path = rc_strcatpaths(RC_SVCDIR, "options", service, (char *) NULL);
|
||||
char *file = rc_strcatpaths(path, option, (char *) NULL);
|
||||
bool retval = false;
|
||||
char file[PATH_MAX];
|
||||
char *p = file;
|
||||
|
||||
if (mkdir(path, 0755) != 0 && errno != EEXIST) {
|
||||
free(path);
|
||||
free(file);
|
||||
p += snprintf(file, sizeof(file), RC_SVCDIR "/options/%s", service);
|
||||
if (mkdir(file, 0755) != 0 && errno != EEXIST)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((fp = fopen(file, "w"))) {
|
||||
if (value)
|
||||
fprintf(fp, "%s", value);
|
||||
fclose(fp);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
free(path);
|
||||
free(file);
|
||||
return retval;
|
||||
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)
|
||||
|
||||
static pid_t _exec_service(const char *service, const char *arg)
|
||||
{
|
||||
char *file;
|
||||
char *fifo;
|
||||
char fifo[PATH_MAX];
|
||||
pid_t pid = -1;
|
||||
sigset_t full;
|
||||
sigset_t old;
|
||||
@@ -703,11 +685,9 @@ static pid_t _exec_service(const char *service, const char *arg)
|
||||
}
|
||||
|
||||
/* We create a fifo so that other services can wait until we complete */
|
||||
fifo = rc_strcatpaths(RC_SVCDIR, "exclusive", basename_c(service),
|
||||
(char *) NULL);
|
||||
|
||||
snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s",
|
||||
basename_c(service));
|
||||
if (mkfifo(fifo, 0600) != 0 && errno != EEXIST) {
|
||||
free(fifo);
|
||||
free(file);
|
||||
return -1;
|
||||
}
|
||||
@@ -745,7 +725,6 @@ static pid_t _exec_service(const char *service, const char *arg)
|
||||
|
||||
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||
|
||||
free(fifo);
|
||||
free(file);
|
||||
|
||||
return pid;
|
||||
@@ -782,28 +761,24 @@ librc_hidden_def(rc_service_start)
|
||||
bool rc_service_schedule_start(const char *service,
|
||||
const char *service_to_start)
|
||||
{
|
||||
char *dir;
|
||||
char file[PATH_MAX];
|
||||
char *p = file;
|
||||
char *init;
|
||||
char *file;
|
||||
bool retval;
|
||||
|
||||
/* service may be a provided service, like net */
|
||||
if (! service || ! rc_service_exists(service_to_start))
|
||||
return false;
|
||||
|
||||
dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
|
||||
(char *) NULL);
|
||||
if (mkdir(dir, 0755) != 0 && errno != EEXIST) {
|
||||
free(dir);
|
||||
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);
|
||||
file = rc_strcatpaths(dir, basename_c(service_to_start), (char *) NULL);
|
||||
snprintf(p, sizeof(file) - (p - file), "/%s", basename_c(service_to_start));
|
||||
retval = (exists(file) || symlink(init, file) == 0);
|
||||
free(init);
|
||||
free(file);
|
||||
free(dir);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -811,20 +786,19 @@ librc_hidden_def(rc_service_schedule_start)
|
||||
|
||||
bool rc_service_schedule_clear(const char *service)
|
||||
{
|
||||
char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
|
||||
(char *) NULL);
|
||||
bool retval;
|
||||
char dir[PATH_MAX];
|
||||
|
||||
if (! (retval = rm_dir(dir, true)) && errno == ENOENT)
|
||||
retval = true;
|
||||
free(dir);
|
||||
return retval;
|
||||
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;
|
||||
char dir[PATH_MAX];
|
||||
RC_STRINGLIST *list;
|
||||
|
||||
if (! runlevel) {
|
||||
@@ -855,43 +829,47 @@ RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel)
|
||||
/* These special levels never contain any services */
|
||||
if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 ||
|
||||
strcmp(runlevel, RC_LEVEL_SINGLE) == 0) {
|
||||
list = rc_stringlist_new();
|
||||
return list;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL);
|
||||
snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel);
|
||||
list = ls_dir(dir, LS_INITD);
|
||||
free(dir);
|
||||
return list;
|
||||
}
|
||||
librc_hidden_def(rc_services_in_runlevel)
|
||||
|
||||
RC_STRINGLIST *rc_services_in_state(RC_SERVICE state)
|
||||
{
|
||||
char *dir = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(state),
|
||||
(char *) NULL);
|
||||
RC_STRINGLIST *services;
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRINGLIST *dirs;
|
||||
RC_STRING *d;
|
||||
char *p;
|
||||
char dir[PATH_MAX];
|
||||
char *p = dir;
|
||||
|
||||
if (state == RC_SERVICE_SCHEDULED) {
|
||||
dirs = ls_dir(dir, 0);
|
||||
list = rc_stringlist_new();
|
||||
TAILQ_FOREACH(d, dirs, entries) {
|
||||
p = rc_strcatpaths(dir, d->value, (char *) NULL);
|
||||
services = ls_dir(p, LS_INITD);
|
||||
free(p);
|
||||
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);
|
||||
if (! dirs)
|
||||
return NULL;
|
||||
|
||||
TAILQ_FOREACH(d, dirs, entries) {
|
||||
snprintf(p, sizeof(dir) - (p - dir), "/%s", d->value);
|
||||
services = ls_dir(dir, LS_INITD);
|
||||
if (! list)
|
||||
services = list;
|
||||
else if (services) {
|
||||
TAILQ_CONCAT(list, services, entries);
|
||||
free(services);
|
||||
}
|
||||
rc_stringlist_free(dirs);
|
||||
} else {
|
||||
list = ls_dir(dir, LS_INITD);
|
||||
}
|
||||
rc_stringlist_free(dirs);
|
||||
|
||||
free(dir);
|
||||
return list;
|
||||
}
|
||||
librc_hidden_def(rc_services_in_state)
|
||||
@@ -900,9 +878,11 @@ bool rc_service_add(const char *runlevel, const char *service)
|
||||
{
|
||||
bool retval;
|
||||
char *init;
|
||||
char *file;
|
||||
char file[PATH_MAX];
|
||||
char path[MAXPATHLEN] = { '\0' };
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
char binit[PATH_MAX];
|
||||
char *i;
|
||||
|
||||
if (! rc_runlevel_exists(runlevel)) {
|
||||
errno = ENOENT;
|
||||
@@ -914,13 +894,15 @@ bool rc_service_add(const char *runlevel, const char *service)
|
||||
return false;
|
||||
}
|
||||
|
||||
init = rc_service_resolve(service);
|
||||
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);
|
||||
free(init);
|
||||
p = realpath(dirname (init), path);
|
||||
if (! *p)
|
||||
return false;
|
||||
|
||||
@@ -929,33 +911,25 @@ bool rc_service_add(const char *runlevel, const char *service)
|
||||
errno = EPERM;
|
||||
return false;
|
||||
}
|
||||
init = rc_strcatpaths(RC_INITDIR, service, (char *) NULL);
|
||||
snprintf(binit, sizeof(binit), RC_INITDIR "/%s", service);
|
||||
i = binit;
|
||||
}
|
||||
|
||||
file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service),
|
||||
(char *) NULL);
|
||||
retval = (symlink(init, file) == 0);
|
||||
retval = (symlink(i, file) == 0);
|
||||
free(init);
|
||||
free(file);
|
||||
return retval;
|
||||
}
|
||||
librc_hidden_def(rc_service_add)
|
||||
|
||||
bool rc_service_delete (const char *runlevel, const char *service)
|
||||
{
|
||||
char *file;
|
||||
bool retval = false;
|
||||
char file[PATH_MAX];
|
||||
|
||||
if (! runlevel || ! service)
|
||||
return false;
|
||||
|
||||
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c(service),
|
||||
(char *) NULL);
|
||||
snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
|
||||
runlevel, basename_c(service));
|
||||
if (unlink(file) == 0)
|
||||
retval = true;
|
||||
|
||||
free(file);
|
||||
return retval;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
librc_hidden_def(rc_service_delete)
|
||||
|
||||
@@ -964,15 +938,19 @@ RC_STRINGLIST *rc_services_scheduled_by(const char *service)
|
||||
RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRING *dir;
|
||||
char *file;
|
||||
char file[PATH_MAX];
|
||||
|
||||
if (! dirs)
|
||||
return NULL;
|
||||
|
||||
list = rc_stringlist_new();
|
||||
TAILQ_FOREACH (dir, dirs, entries) {
|
||||
file = rc_strcatpaths(RC_SVCDIR, "scheduled", dir->value,
|
||||
service, (char *) NULL);
|
||||
if (exists(file))
|
||||
snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
|
||||
dir->value, service);
|
||||
if (exists(file)) {
|
||||
if (! list)
|
||||
list = rc_stringlist_new();
|
||||
rc_stringlist_add(list, file);
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
rc_stringlist_free(dirs);
|
||||
|
||||
@@ -982,11 +960,10 @@ librc_hidden_def(rc_services_scheduled_by)
|
||||
|
||||
RC_STRINGLIST *rc_services_scheduled(const char *service)
|
||||
{
|
||||
char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
|
||||
(char *) NULL);
|
||||
RC_STRINGLIST *list = ls_dir(dir, LS_INITD);
|
||||
char dir[PATH_MAX];
|
||||
|
||||
free(dir);
|
||||
return list;
|
||||
snprintf(dir, sizeof(dir), "RC_SVCDIR/scheduled/%s",
|
||||
basename_c(service));
|
||||
return ls_dir(dir, LS_INITD);
|
||||
}
|
||||
librc_hidden_def(rc_services_scheduled)
|
||||
|
||||
@@ -112,7 +112,6 @@ 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_strcatpaths)
|
||||
librc_hidden_proto(rc_stringlist_add)
|
||||
librc_hidden_proto(rc_stringlist_addu)
|
||||
librc_hidden_proto(rc_stringlist_delete)
|
||||
|
||||
@@ -27,17 +27,6 @@
|
||||
#ifndef __RC_H__
|
||||
#define __RC_H__
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC__MINOR)
|
||||
# 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>
|
||||
@@ -444,13 +433,6 @@ void rc_stringlist_sort(RC_STRINGLIST **);
|
||||
* @param list to free */
|
||||
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 *, const char *, ...) SENTINEL;
|
||||
|
||||
typedef struct rc_pid
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
@@ -26,6 +26,7 @@ global:
|
||||
rc_service_delete;
|
||||
rc_service_description;
|
||||
rc_service_exists;
|
||||
rc_service_extra_commands;
|
||||
rc_service_in_runlevel;
|
||||
rc_service_mark;
|
||||
rc_service_options;
|
||||
@@ -42,7 +43,6 @@ global:
|
||||
rc_service_state;
|
||||
rc_service_value_get;
|
||||
rc_service_value_set;
|
||||
rc_strcatpaths;
|
||||
rc_stringlist_add;
|
||||
rc_stringlist_addu;
|
||||
rc_stringlist_delete;
|
||||
|
||||
Reference in New Issue
Block a user