summaryrefslogtreecommitdiff
path: root/src/librc/librc-depend.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/librc/librc-depend.c')
-rw-r--r--src/librc/librc-depend.c1012
1 files changed, 447 insertions, 565 deletions
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
index 2247036..8617d75 100644
--- a/src/librc/librc-depend.c
+++ b/src/librc/librc-depend.c
@@ -37,31 +37,18 @@
static const char *bootlevel = NULL;
-/* We use this so we can pass our char array through many functions */
-struct lhead
-{
- char **list;
-};
-
-static void *xzalloc (size_t size)
-{
- void *value = xmalloc (size);
- memset (value, 0, size);
- return (value);
-}
-
-static char *get_shell_value (char *string)
+static char *get_shell_value(char *string)
{
char *p = string;
char *e;
if (! string)
- return (NULL);
+ return NULL;
if (*p == '\'')
p++;
- e = p + strlen (p) - 1;
+ e = p + strlen(p) - 1;
if (*e == '\n')
*e-- = 0;
if (*e == '\'')
@@ -70,191 +57,184 @@ static char *get_shell_value (char *string)
if (*p != 0)
return p;
- return (NULL);
+ return NULL;
}
-void rc_deptree_free (rc_depinfo_t *deptree)
+void rc_deptree_free(RC_DEPTREE *deptree)
{
- rc_depinfo_t *di = deptree;
+ RC_DEPINFO *di;
+ RC_DEPINFO *di2;
+ RC_DEPTYPE *dt;
+ RC_DEPTYPE *dt2;
+
+ if (! deptree)
+ return;
+
+ di = STAILQ_FIRST(deptree);
while (di)
{
- rc_depinfo_t *dip = di->next;
- rc_deptype_t *dt = di->depends;
- free (di->service);
+ di2 = STAILQ_NEXT(di, entries);
+ dt = STAILQ_FIRST(&di->depends);
while (dt)
{
- rc_deptype_t *dtp = dt->next;
- free (dt->type);
- rc_strlist_free (dt->services);
- free (dt);
- dt = dtp;
+ dt2 = STAILQ_NEXT(dt, entries);
+ rc_stringlist_free(dt->services);
+ free(dt->type);
+ free(dt);
+ dt = dt2;
}
- free (di);
- di = dip;
+ free(di->service);
+ free(di);
+ di = di2;
}
+ free(deptree);
}
librc_hidden_def(rc_deptree_free)
-static rc_depinfo_t *get_depinfo (const rc_depinfo_t *deptree,
- const char *service)
+static RC_DEPINFO *get_depinfo(const RC_DEPTREE *deptree,
+ const char *service)
{
- const rc_depinfo_t *di;
-
- if (! deptree || ! service)
- return (NULL);
+ RC_DEPINFO *di;
- for (di = deptree; di; di = di->next)
- if (strcmp (di->service, service) == 0)
- return ((rc_depinfo_t *)di);
+ STAILQ_FOREACH(di, deptree, entries)
+ if (strcmp(di->service, service) == 0)
+ return di;
- return (NULL);
+ return NULL;
}
-static rc_deptype_t *get_deptype (const rc_depinfo_t *depinfo,
- const char *type)
+static RC_DEPTYPE *get_deptype(const RC_DEPINFO *depinfo,
+ const char *type)
{
- rc_deptype_t *dt;
+ RC_DEPTYPE *dt;
- if (! depinfo || !type)
- return (NULL);
+ STAILQ_FOREACH(dt, &depinfo->depends, entries)
+ if (strcmp(dt->type, type) == 0)
+ return dt;
- for (dt = depinfo->depends; dt; dt = dt->next)
- if (strcmp (dt->type, type) == 0)
- return (dt);
-
- return (NULL);
+ return NULL;
}
-rc_depinfo_t *rc_deptree_load (void)
+RC_DEPTREE *rc_deptree_load(void)
{
FILE *fp;
- rc_depinfo_t *deptree = NULL;
- rc_depinfo_t *depinfo = NULL;
- rc_deptype_t *deptype = NULL;
+ RC_DEPTREE *deptree;
+ RC_DEPINFO *depinfo = NULL;
+ RC_DEPTYPE *deptype = NULL;
char *line;
char *type;
char *p;
char *e;
int i;
- if (! (fp = fopen (RC_DEPTREE, "r")))
- return (NULL);
+ if (!(fp = fopen(RC_DEPTREE_CACHE, "r")))
+ return NULL;
+
+ deptree = xmalloc(sizeof(*deptree));
+ STAILQ_INIT(deptree);
- while ((line = rc_getline (fp)))
+ while ((line = rc_getline(fp)))
{
p = line;
- e = strsep (&p, "_");
- if (! e || strcmp (e, "depinfo") != 0)
+ e = strsep(&p, "_");
+ if (! e || strcmp(e, "depinfo") != 0)
goto next;
e = strsep (&p, "_");
- if (! e || sscanf (e, "%d", &i) != 1)
+ if (! e || sscanf(e, "%d", &i) != 1)
goto next;
- if (! (type = strsep (&p, "_=")))
+ if (! (type = strsep(&p, "_=")))
goto next;
- if (strcmp (type, "service") == 0)
+ if (strcmp(type, "service") == 0)
{
/* Sanity */
- e = get_shell_value (p);
+ e = get_shell_value(p);
if (! e || *e == '\0')
goto next;
- if (! deptree)
- {
- deptree = xzalloc (sizeof (*deptree));
- depinfo = deptree;
- }
- else
- {
- depinfo->next = xzalloc (sizeof (*depinfo->next));
- depinfo = depinfo->next;
- }
- depinfo->service = xstrdup (e);
+ depinfo = xmalloc(sizeof(*depinfo));
+ STAILQ_INIT(&depinfo->depends);
+ depinfo->service = xstrdup(e);
+ STAILQ_INSERT_TAIL(deptree, depinfo, entries);
deptype = NULL;
goto next;
}
- e = strsep (&p, "=");
- if (! e || sscanf (e, "%d", &i) != 1)
+ e = strsep(&p, "=");
+ if (! e || sscanf(e, "%d", &i) != 1)
goto next;
/* Sanity */
- e = get_shell_value (p);
+ e = get_shell_value(p);
if (! e || *e == '\0')
goto next;
- if (! deptype)
- {
- depinfo->depends = xzalloc (sizeof (*depinfo->depends));
- deptype = depinfo->depends;
- }
- else
- if (strcmp (deptype->type, type) != 0)
- {
- deptype->next = xzalloc (sizeof (*deptype->next));
- deptype = deptype->next;
- }
-
- if (! deptype->type)
+ if (! deptype || strcmp(deptype->type, type) != 0) {
+ deptype = xmalloc(sizeof(*deptype));
+ deptype->services = rc_stringlist_new();
deptype->type = xstrdup (type);
+ STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
+ }
- rc_strlist_addsort (&deptype->services, e);
-
+ rc_stringlist_add(deptype->services, e);
next:
- free (line);
+ free(line);
}
- fclose (fp);
-
- return (deptree);
+ fclose(fp);
+
+ return deptree;
}
librc_hidden_def(rc_deptree_load)
-static bool valid_service (const char *runlevel, const char *service)
+static bool valid_service(const char *runlevel, const char *service)
{
- rc_service_state_t state = rc_service_state (service);
+ RC_SERVICE state = rc_service_state(service);
return ((strcmp (runlevel, bootlevel) != 0 &&
- rc_service_in_runlevel (service, bootlevel)) ||
- rc_service_in_runlevel (service, runlevel) ||
+ rc_service_in_runlevel(service, bootlevel)) ||
+ rc_service_in_runlevel(service, runlevel) ||
state & RC_SERVICE_COLDPLUGGED ||
state & RC_SERVICE_STARTED);
}
-static bool get_provided1 (const char *runlevel, struct lhead *providers,
- rc_deptype_t *deptype,
- const char *level, bool coldplugged,
- rc_service_state_t state)
+static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
+ RC_DEPTYPE *deptype,
+ const char *level, bool coldplugged,
+ RC_SERVICE state)
{
- char *service;
- int i;
+ RC_STRING *service;
+ RC_SERVICE st;
bool retval = false;
+ bool ok;
+ const char *svc;
+
+ TAILQ_FOREACH(service, deptype->services, entries) {
+ ok = true;
+ svc = service->value;
+ st = rc_service_state(svc);
- STRLIST_FOREACH (deptype->services, service, i)
- {
- bool ok = true;
- rc_service_state_t s = rc_service_state (service);
if (level)
- ok = rc_service_in_runlevel (service, level);
+ ok = rc_service_in_runlevel(svc, level);
else if (coldplugged)
- ok = (s & RC_SERVICE_COLDPLUGGED &&
- ! rc_service_in_runlevel (service, runlevel) &&
- ! rc_service_in_runlevel (service, bootlevel));
+ ok = (st & RC_SERVICE_COLDPLUGGED &&
+ ! rc_service_in_runlevel(svc, runlevel) &&
+ ! rc_service_in_runlevel(svc, bootlevel));
if (! ok)
continue;
switch (state) {
case RC_SERVICE_STARTED:
- ok = (s & RC_SERVICE_STARTED);
+ ok = (st & RC_SERVICE_STARTED);
break;
case RC_SERVICE_INACTIVE:
case RC_SERVICE_STARTING:
case RC_SERVICE_STOPPING:
- ok = (s & RC_SERVICE_STARTING ||
- s & RC_SERVICE_STOPPING ||
- s & RC_SERVICE_INACTIVE);
+ ok = (st & RC_SERVICE_STARTING ||
+ st & RC_SERVICE_STOPPING ||
+ st & RC_SERVICE_INACTIVE);
break;
default:
break;
@@ -264,10 +244,10 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers,
continue;
retval = true;
- rc_strlist_add (&providers->list, service);
+ rc_stringlist_add(providers, svc);
}
- return (retval);
+ return retval;
}
/* Work out if a service is provided by another service.
@@ -279,50 +259,41 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers,
If there are any bugs in rc-depend, they will probably be here as
provided dependancy can change depending on runlevel state.
*/
-static char **get_provided (const rc_depinfo_t *deptree,
- const rc_depinfo_t *depinfo,
- const char *runlevel, int options)
+static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
+ const char *runlevel, int options)
{
- rc_deptype_t *dt;
- struct lhead providers;
- char *service;
- int i;
+ RC_DEPTYPE *dt;
+ RC_STRINGLIST *providers = rc_stringlist_new();
+ RC_STRING *service;
- if (! deptree || ! depinfo)
- return (NULL);
-
- if (rc_service_exists (depinfo->service))
- return (NULL);
-
- dt = get_deptype (depinfo, "providedby");
+ dt = get_deptype(depinfo, "providedby");
if (! dt)
- return (NULL);
+ return providers;
- memset (&providers, 0, sizeof (providers));
/* If we are stopping then all depends are true, regardless of state.
This is especially true for net services as they could force a restart
of the local dns resolver which may depend on net. */
if (options & RC_DEP_STOP)
{
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_add (&providers.list, service);
-
- return (providers.list);
+ TAILQ_FOREACH(service, dt->services, entries)
+ rc_stringlist_add(providers, service->value);
+ return providers;
}
/* If we're strict or startng, then only use what we have in our
* runlevel and bootlevel. If we starting then check cold-plugged too. */
if (options & RC_DEP_STRICT || options & RC_DEP_START)
{
- STRLIST_FOREACH (dt->services, service, i)
- if (rc_service_in_runlevel (service, runlevel) ||
- rc_service_in_runlevel (service, bootlevel) ||
+
+ TAILQ_FOREACH(service, dt->services, entries)
+ if (rc_service_in_runlevel(service->value, runlevel) ||
+ rc_service_in_runlevel(service->value, bootlevel) ||
(options & RC_DEP_START &&
- rc_service_state (service) & RC_SERVICE_COLDPLUGGED))
- rc_strlist_add (&providers.list, service);
+ rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED))
+ rc_stringlist_add(providers, service->value);
- if (providers.list)
- return (providers.list);
+ if (TAILQ_FIRST(providers))
+ return providers;
}
/* OK, we're not strict or there were no services in our runlevel.
@@ -333,225 +304,211 @@ static char **get_provided (const rc_depinfo_t *deptree,
We apply this to our runlevel, coldplugged services, then bootlevel
and finally any running.*/
#define DO \
- if (providers.list && providers.list[0] && providers.list[1]) \
- { \
- rc_strlist_free (providers.list); \
- return (NULL); \
- } \
- else if (providers.list) \
- return providers.list; \
+ if (TAILQ_FIRST(providers)) { \
+ if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
+ rc_stringlist_free(providers); \
+ providers = rc_stringlist_new(); \
+ } \
+ return providers; \
+ }
/* Anything in the runlevel has to come first */
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTING))
- return (providers.list);
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING))
+ return providers;
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
+ return providers;
/* Check coldplugged services */
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
+ return providers;
/* Check bootlevel if we're not in it */
if (bootlevel && strcmp (runlevel, bootlevel) != 0)
{
- if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
+ return providers;
}
/* Check coldplugged services */
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STOPPED))
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
{ DO }
/* Check manually started */
- if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING))
+ return providers;
/* Nothing started then. OK, lets get the stopped services */
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
+ return providers;
if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
- && (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
- return (providers.list);
+ && (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
+ return providers;
/* Still nothing? OK, list all services */
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_add (&providers.list, service);
+ TAILQ_FOREACH(service, dt->services, entries)
+ rc_stringlist_add(providers, service->value);
- return (providers.list);
+ return providers;
}
-static void visit_service (const rc_depinfo_t *deptree,
- const char * const *types,
- struct lhead *sorted, struct lhead *visited,
- const rc_depinfo_t *depinfo,
+static void visit_service (const RC_DEPTREE *deptree,
+ const RC_STRINGLIST *types,
+ RC_STRINGLIST *sorted,
+ RC_STRINGLIST *visited,
+ const RC_DEPINFO *depinfo,
const char *runlevel, int options)
{
- int i, j, k;
- char *lp;
- const char *item;
- char *service;
- rc_depinfo_t *di;
- rc_deptype_t *dt;
- char **provides;
- char *svcname;
-
- if (! deptree || !sorted || !visited || !depinfo)
- return;
+ RC_STRING *type;
+ RC_STRING *service;
+ RC_DEPTYPE *dt;
+ RC_DEPINFO *di;
+ RC_STRINGLIST *provided;
+ RC_STRING *p;
+ const char *svcname;
/* Check if we have already visited this service or not */
- STRLIST_FOREACH (visited->list, item, i)
- if (strcmp (item, depinfo->service) == 0)
+ TAILQ_FOREACH(type, visited, entries)
+ if (strcmp(type->value, depinfo->service) == 0)
return;
/* Add ourselves as a visited service */
- rc_strlist_add (&visited->list, depinfo->service);
+ rc_stringlist_add(visited, depinfo->service);
- STRLIST_FOREACH (types, item, i)
+ TAILQ_FOREACH(type, types, entries)
{
- if ((dt = get_deptype (depinfo, item)))
- {
- STRLIST_FOREACH (dt->services, service, j)
+ if (!(dt = get_deptype(depinfo, type->value)))
+ continue;
+
+ TAILQ_FOREACH(service, dt->services, entries) {
+ if (! options & RC_DEP_TRACE ||
+ strcmp(type->value, "iprovide") == 0)
{
- if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0)
- {
- rc_strlist_add (&sorted->list, service);
- continue;
- }
+ rc_stringlist_add(sorted, service->value);
+ continue;
+ }
- di = get_depinfo (deptree, service);
- if ((provides = get_provided (deptree, di, runlevel, options)))
- {
- STRLIST_FOREACH (provides, lp, k)
- {
- di = get_depinfo (deptree, lp);
- if (di && (strcmp (item, "ineed") == 0 ||
- strcmp (item, "needsme") == 0 ||
- valid_service (runlevel, di->service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- }
- rc_strlist_free (provides);
+ if (!(di = get_depinfo(deptree, service->value)))
+ continue;
+ provided = get_provided(di, runlevel, options);
+
+ if (TAILQ_FIRST(provided)) {
+ TAILQ_FOREACH(p, provided, entries) {
+ di = get_depinfo(deptree, p->value);
+ if (di &&
+ (strcmp(type->value, "ineed") == 0 ||
+ strcmp(type->value, "needsme") == 0 ||
+ valid_service(runlevel, di->service)))
+ visit_service(deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
}
- else
- if (di && (strcmp (item, "ineed") == 0 ||
- strcmp (item, "needsme") == 0 ||
- valid_service (runlevel, service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
}
+ else if (di &&
+ (strcmp(type->value, "ineed") == 0 ||
+ strcmp(type->value, "needsme") == 0 ||
+ valid_service(runlevel, service->value)))
+ visit_service(deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
+
+ rc_stringlist_free(provided);
}
}
/* Now visit the stuff we provide for */
if (options & RC_DEP_TRACE &&
- (dt = get_deptype (depinfo, "iprovide")))
+ (dt = get_deptype(depinfo, "iprovide")))
{
- STRLIST_FOREACH (dt->services, service, i)
- {
- if ((di = get_depinfo (deptree, service)))
- if ((provides = get_provided (deptree, di, runlevel, options)))
- {
- STRLIST_FOREACH (provides, lp, j)
- if (strcmp (lp, depinfo->service) == 0)
- {
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- break;
- }
- rc_strlist_free (provides);
+ TAILQ_FOREACH(service, dt->services, entries) {
+ if (!(di = get_depinfo(deptree, service->value)))
+ continue;
+
+ provided = get_provided(di, runlevel, options);
+ TAILQ_FOREACH(p, provided, entries)
+ if (strcmp (p->value, depinfo->service) == 0) {
+ //visit_service (deptree, types, sorted, visited, di,
+ // runlevel, options | RC_DEP_TRACE);
+ break;
}
+ rc_stringlist_free(provided);
}
}
/* We've visited everything we need, so add ourselves unless we
are also the service calling us or we are provided by something */
svcname = getenv("SVCNAME");
- if (! svcname || strcmp (svcname, depinfo->service) != 0)
- if (! get_deptype (depinfo, "providedby"))
- rc_strlist_add (&sorted->list, depinfo->service);
+ if (! svcname || strcmp(svcname, depinfo->service) != 0)
+ if (! get_deptype(depinfo, "providedby"))
+ rc_stringlist_add(sorted, depinfo->service);
}
-char **rc_deptree_depend (const rc_depinfo_t *deptree,
- const char *service, const char *type)
+RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
+ const char *service, const char *type)
{
- rc_depinfo_t *di;
- rc_deptype_t *dt;
- char **svcs = NULL;
- int i;
- char *svc;
+ RC_DEPINFO *di;
+ RC_DEPTYPE *dt;
+ RC_STRINGLIST *svcs;
+ RC_STRING *svc;
- if (! (di = get_depinfo (deptree, service)) ||
- ! (dt = get_deptype (di, type)))
+ if (!(di = get_depinfo(deptree, service)) ||
+ ! (dt = get_deptype(di, type)))
{
errno = ENOENT;
- return (NULL);
+ return NULL;
}
/* For consistency, we copy the array */
- STRLIST_FOREACH (dt->services, svc, i)
- rc_strlist_add (&svcs, svc);
+ svcs = rc_stringlist_new();
+ TAILQ_FOREACH(svc, dt->services, entries)
+ rc_stringlist_add(svcs, svc->value);
- return (svcs);
+ return svcs;
}
librc_hidden_def(rc_deptree_depend)
-char **rc_deptree_depends (const rc_depinfo_t *deptree,
- const char *const *types,
- const char *const *services,
- const char *runlevel, int options)
+RC_STRINGLIST *rc_deptree_depends (const RC_DEPTREE *deptree,
+ const RC_STRINGLIST *types,
+ const RC_STRINGLIST *services,
+ const char *runlevel, int options)
{
- struct lhead sorted;
- struct lhead visited;
- rc_depinfo_t *di;
- const char *service;
- int i;
-
- if (! deptree || ! services)
- return (NULL);
-
- memset (&sorted, 0, sizeof (sorted));
- memset (&visited, 0, sizeof (visited));
+ RC_STRINGLIST *sorted = rc_stringlist_new();
+ RC_STRINGLIST *visited = rc_stringlist_new();
+ RC_DEPINFO *di;
+ const RC_STRING *service;
bootlevel = getenv ("RC_BOOTLEVEL");
if (! bootlevel)
bootlevel = RC_LEVEL_BOOT;
- STRLIST_FOREACH (services, service, i)
- {
- if (! (di = get_depinfo (deptree, service))) {
+ TAILQ_FOREACH(service, services, entries) {
+ if (! (di = get_depinfo(deptree, service->value))) {
errno = ENOENT;
continue;
}
if (types)
- visit_service (deptree, types, &sorted, &visited,
+ visit_service (deptree, types, sorted, visited,
di, runlevel, options);
}
- rc_strlist_free (visited.list);
- return (sorted.list);
+ rc_stringlist_free (visited);
+ return sorted;
}
librc_hidden_def(rc_deptree_depends)
- static const char * const order_types[] = { "ineed", "iuse", "iafter", NULL };
-char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
- int options)
+RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
+ const char *runlevel, int options)
{
- char **list = NULL;
- char **services = NULL;
- bool reverse = false;
- char **tmp = NULL;
-
- if (! runlevel)
- return (NULL);
+ RC_STRINGLIST *list;
+ RC_STRINGLIST *list2;
+ RC_STRINGLIST *types;
+ RC_STRINGLIST *services;
bootlevel = getenv ("RC_BOOTLEVEL");
if (! bootlevel)
@@ -562,47 +519,48 @@ char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
{
- list = rc_services_in_state (RC_SERVICE_STARTED);
+ list = rc_services_in_state(RC_SERVICE_STARTED);
- tmp = rc_services_in_state (RC_SERVICE_INACTIVE);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_state (RC_SERVICE_INACTIVE);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
- tmp = rc_services_in_state (RC_SERVICE_STARTING);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
- reverse = true;
+ list2 = rc_services_in_state (RC_SERVICE_STARTING);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
} else {
list = rc_services_in_runlevel (runlevel);
/* Add coldplugged services */
- tmp = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
/* If we're not the boot runlevel then add that too */
if (strcmp (runlevel, bootlevel) != 0) {
- tmp = rc_services_in_runlevel (bootlevel);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_runlevel (bootlevel);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
}
}
/* Now we have our lists, we need to pull in any dependencies
and order them */
- services = rc_deptree_depends (deptree, order_types, (const char **) list,
- runlevel,
- RC_DEP_STRICT | RC_DEP_TRACE | options);
- rc_strlist_free (list);
+ types = rc_stringlist_new();
+ rc_stringlist_add(types, "ineed");
+ rc_stringlist_add(types, "iuse");
+ rc_stringlist_add(types, "iafter");
- if (reverse)
- rc_strlist_reverse (services);
+ services = rc_deptree_depends(deptree, types, list, runlevel,
+ RC_DEP_STRICT | RC_DEP_TRACE | options);
+ rc_stringlist_free (list);
+ rc_stringlist_free (types);
- return (services);
+ return services;
}
librc_hidden_def(rc_deptree_order)
-bool rc_newer_than (const char *source, const char *target)
+bool rc_newer_than(const char *source, const char *target)
{
struct stat buf;
time_t mtime;
@@ -613,38 +571,38 @@ bool rc_newer_than (const char *source, const char *target)
int serrno = errno;
/* We have to exist */
- if (stat (source, &buf) != 0)
- return (false);
+ if (stat(source, &buf) != 0)
+ return false;
mtime = buf.st_mtime;
/* Of course we are newer than targets that don't exist
such as broken symlinks */
- if (stat (target, &buf) != 0)
- return (true);
+ if (stat(target, &buf) != 0)
+ return true;
if (mtime < buf.st_mtime)
- return (false);
+ return false;
/* If not a dir then reset errno */
- if (! (dp = opendir (target))) {
+ if (! (dp = opendir(target))) {
errno = serrno;
- return (true);
+ return true;
}
/* Check if we're newer than all the entries in the dir */
- while ((d = readdir (dp))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
- path = rc_strcatpaths (target, d->d_name, (char *) NULL);
- newer = rc_newer_than (source, path);
- free (path);
+ path = rc_strcatpaths(target, d->d_name, (char *) NULL);
+ newer = rc_newer_than(source, path);
+ free(path);
if (! newer)
break;
}
- closedir (dp);
+ closedir(dp);
- return (newer);
+ return newer;
}
librc_hidden_def(rc_newer_than)
@@ -652,12 +610,12 @@ typedef struct deppair
{
const char *depend;
const char *addto;
-} deppair_t;
+} DEPPAIR;
-static const deppair_t deppairs[] = {
- { "ineed", "needsme" },
- { "iuse", "usesme" },
- { "iafter", "ibefore" },
+static const DEPPAIR deppairs[] = {
+ { "ineed", "needsme" },
+ { "iuse", "usesme" },
+ { "iafter", "ibefore" },
{ "ibefore", "iafter" },
{ "iprovide", "providedby" },
{ NULL, NULL }
@@ -679,168 +637,151 @@ static const char *const depdirs[] =
NULL
};
-bool rc_deptree_update_needed (void)
+bool rc_deptree_update_needed(void)
{
bool newer = false;
- char **config;
- char *service;
+ RC_STRINGLIST *config;
+ RC_STRING *s;
int i;
/* Create base directories if needed */
for (i = 0; depdirs[i]; i++)
- if (mkdir (depdirs[i], 0755) != 0 && errno != EEXIST)
- fprintf (stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno));
+ if (mkdir(depdirs[i], 0755) != 0 && errno != EEXIST)
+ fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno));
/* Quick test to see if anything we use has changed and we have
* data in our deptree */
- if (! existss (RC_DEPTREE) ||
- ! rc_newer_than (RC_DEPTREE, RC_INITDIR) ||
- ! rc_newer_than (RC_DEPTREE, RC_CONFDIR) ||
+ if (! existss(RC_DEPTREE_CACHE) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
#ifdef RC_PKG_INITDIR
- ! rc_newer_than (RC_DEPTREE, RC_PKG_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
#endif
#ifdef RC_PKG_CONFDIR
- ! rc_newer_than (RC_DEPTREE, RC_PKG_CONFDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
#endif
#ifdef RC_LOCAL_INITDIR
- ! rc_newer_than (RC_DEPTREE, RC_LOCAL_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
#endif
#ifdef RC_LOCAL_CONFDIR
- ! rc_newer_than (RC_DEPTREE, RC_LOCAL_CONFDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
#endif
- ! rc_newer_than (RC_DEPTREE, "/etc/rc.conf"))
- return (true);
+ ! rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
+ return true;
/* Some init scripts dependencies change depending on config files
* outside of baselayout, like syslog-ng, so we check those too. */
config = rc_config_list (RC_DEPCONFIG);
- STRLIST_FOREACH (config, service, i) {
- if (! rc_newer_than (RC_DEPTREE, service)) {
+ TAILQ_FOREACH(s, config, entries) {
+ if (! rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
newer = true;
break;
}
}
- rc_strlist_free (config);
+ rc_stringlist_free(config);
- return (newer);
+ return newer;
}
librc_hidden_def(rc_deptree_update_needed)
- /* This is a 5 phase operation
- Phase 1 is a shell script which loads each init script and config in turn
- and echos their dependency info to stdout
- Phase 2 takes that and populates a depinfo object with that data
- Phase 3 adds any provided services to the depinfo object
- Phase 4 scans that depinfo object and puts in backlinks
- Phase 5 saves the depinfo object to disk
- */
-bool rc_deptree_update (void)
+/* This is a 5 phase operation
+ Phase 1 is a shell script which loads each init script and config in turn
+ and echos their dependency info to stdout
+ Phase 2 takes that and populates a depinfo object with that data
+ Phase 3 adds any provided services to the depinfo object
+ Phase 4 scans that depinfo object and puts in backlinks
+ Phase 5 saves the depinfo object to disk
+ */
+bool rc_deptree_update(void)
{
+ FILE *fp;
+ RC_DEPTREE *deptree;
+ RC_DEPTREE *providers;
+ RC_DEPINFO *depinfo = NULL;
+ RC_DEPINFO *depinfo_np;
+ RC_DEPINFO *di;
+ RC_DEPTYPE *deptype = NULL;
+ RC_DEPTYPE *dt;
+ RC_DEPTYPE *dt_np;
+ RC_STRINGLIST *config;
+ RC_STRING *s;
+ RC_STRING *s2;
+ RC_DEPTYPE *provide;
+ char *line;
+ char *depend;
char *depends;
char *service;
char *type;
- char *depend;
- char **config = NULL;
- int retval = true;
- FILE *fp;
- rc_depinfo_t *deptree = NULL;
- rc_depinfo_t *depinfo;
- rc_depinfo_t *di;
- rc_depinfo_t *last_depinfo = NULL;
- rc_deptype_t *deptype = NULL;
- rc_deptype_t *dt;
- rc_deptype_t *last_deptype = NULL;
- char **removedp = NULL;
- char *line;
- size_t len;
size_t i;
- size_t j;
size_t k;
- bool already_added;
- const char *sys = rc_sys ();
+ size_t len;
+ int retval = true;
+ const char *sys = rc_sys();
+ char *nosys;
/* Some init scripts need RC_LIBDIR to source stuff
Ideally we should be setting our full env instead */
- if (! getenv ("RC_LIBDIR"))
- setenv ("RC_LIBDIR", RC_LIBDIR, 0);
+ if (! getenv("RC_LIBDIR"))
+ setenv("RC_LIBDIR", RC_LIBDIR, 0);
/* Phase 1 - source all init scripts and print dependencies */
- if (! (fp = popen (GENDEP, "r")))
- return (false);
+ if (! (fp = popen(GENDEP, "r")))
+ return false;
+
+ deptree = xmalloc(sizeof(*deptree));
+ STAILQ_INIT(deptree);
- while ((line = rc_getline (fp)))
+ config = rc_stringlist_new();
+
+ while ((line = rc_getline(fp)))
{
depends = line;
- service = strsep (&depends, " ");
+ service = strsep(&depends, " ");
if (! service || ! *service)
goto next;
- type = strsep (&depends, " ");
+ type = strsep(&depends, " ");
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- last_depinfo = depinfo;
- if (depinfo->service && strcmp (depinfo->service, service) == 0)
- break;
- }
-
- if (! depinfo)
- {
- if (! last_depinfo)
- deptree = depinfo = xzalloc (sizeof (*depinfo));
- else if (! last_depinfo->service)
- depinfo = last_depinfo;
- else
- {
- last_depinfo->next = xzalloc (sizeof (*last_depinfo->next));
- depinfo = last_depinfo->next;
+ if (! depinfo || strcmp(depinfo->service, service) != 0) {
+ deptype = NULL;
+ depinfo = get_depinfo(deptree, service);
+ if (! depinfo) {
+ depinfo = xmalloc(sizeof(*depinfo));
+ STAILQ_INIT(&depinfo->depends);
+ depinfo->service = xstrdup(service);
+ STAILQ_INSERT_TAIL(deptree, depinfo, entries);
}
- depinfo->service = xstrdup (service);
}
-
+
/* We may not have any depends */
if (! type || ! depends)
goto next;
/* Get the type */
- if (strcmp (type, "config") != 0) {
- last_deptype = NULL;
- for (deptype = depinfo->depends; deptype; deptype = deptype->next)
- {
- last_deptype = deptype;
- if (strcmp (deptype->type, type) == 0)
- break;
- }
-
- if (! deptype)
- {
- if (! last_deptype)
- {
- depinfo->depends = xzalloc (sizeof (*depinfo->depends));
- deptype = depinfo->depends;
- }
- else
- {
- last_deptype->next = xzalloc (sizeof (*last_deptype->next));
- deptype = last_deptype->next;
- }
- deptype->type = xstrdup (type);
+ if (strcmp(type, "config") != 0) {
+ if (! deptype || strcmp (deptype->type, type) != 0)
+ deptype = get_deptype(depinfo, type);
+ if (! deptype) {
+ deptype = xmalloc(sizeof(*deptype));
+ deptype->type = xstrdup(type);
+ deptype->services = rc_stringlist_new();
+ STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
}
}
/* Now add each depend to our type.
We do this individually so we handle multiple spaces gracefully */
- while ((depend = strsep (&depends, " ")))
+ while ((depend = strsep(&depends, " ")))
{
if (depend[0] == 0)
continue;
- if (strcmp (type, "config") == 0) {
- rc_strlist_addsort (&config, depend);
+ if (strcmp(type, "config") == 0) {
+ rc_stringlist_add(config, depend);
continue;
}
/* .sh files are not init scripts */
- len = strlen (depend);
+ len = strlen(depend);
if (len > 2 &&
depend[len - 3] == '.' &&
depend[len - 2] == 's' &&
@@ -849,171 +790,114 @@ bool rc_deptree_update (void)
/* Remove our dependency if instructed */
if (depend[0] == '!') {
- rc_strlist_delete (&deptype->services, depend + 1);
+ rc_stringlist_delete(deptype->services, depend + 1);
continue;
}
- rc_strlist_addsort (&deptype->services, depend);
+ rc_stringlist_add(deptype->services, depend);
/* We need to allow `after *; before local;` to work.
* Conversely, we need to allow 'before *; after modules' also */
/* If we're before something, remove us from the after list */
- if (strcmp (type, "ibefore") == 0) {
- if ((dt = get_deptype (depinfo, "iafter")))
- rc_strlist_delete (&dt->services, depend);
+ if (strcmp(type, "ibefore") == 0) {
+ if ((dt = get_deptype(depinfo, "iafter")))
+ rc_stringlist_delete(dt->services, depend);
}
/* If we're after something, remove us from the before list */
if (strcmp (type, "iafter") == 0 ||
strcmp (type, "ineed") == 0 ||
strcmp (type, "iuse") == 0) {
- if ((dt = get_deptype (depinfo, "ibefore")))
- rc_strlist_delete (&dt->services, depend);
+ if ((dt = get_deptype(depinfo, "ibefore")))
+ rc_stringlist_delete(dt->services, depend);
}
}
next:
- free (line);
+ free(line);
}
- pclose (fp);
+ pclose(fp);
/* Phase 2 - if we're a special system, remove services that don't
* work for them. This doesn't stop them from being run directly. */
if (sys) {
- char *nosys;
-
- len = strlen (sys);
- nosys = xmalloc (len + 3);
+ len = strlen(sys);
+ nosys = xmalloc(len + 3);
nosys[0] = 'n';
nosys[1] = 'o';
for (i = 0; i < len; i++)
- nosys[i + 2] = (char) tolower ((int) sys[i]);
+ nosys[i + 2] = (char) tolower((int) sys[i]);
nosys[i + 2] = '\0';
- last_depinfo = NULL;
- depinfo = deptree;
- while (depinfo) {
- bool removed = false;
- if ((deptype = get_deptype (depinfo, "keyword"))) {
- STRLIST_FOREACH (deptype->services, service, i)
- if (strcmp (service, nosys) == 0) {
- if (last_depinfo)
- last_depinfo->next = depinfo->next;
- else
- deptree = depinfo->next;
- removed = true;
- break;
+ STAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np)
+ if ((deptype = get_deptype(depinfo, "keyword")))
+ TAILQ_FOREACH(s, deptype->services, entries)
+ if (strcmp (s->value, nosys) == 0) {
+ provide = get_deptype(depinfo, "iprovide");
+ STAILQ_REMOVE(deptree, depinfo, rc_depinfo, entries);
+ STAILQ_FOREACH(di, deptree, entries) {
+ STAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
+ rc_stringlist_delete(dt->services, depinfo->service);
+ if (provide)
+ TAILQ_FOREACH(s2, provide->services, entries)
+ rc_stringlist_delete(dt->services, s2->value);
+ if (! TAILQ_FIRST(dt->services)) {
+ STAILQ_REMOVE(&di->depends, dt, rc_deptype, entries);
+ free(dt->type);
+ free(dt->services);
+ free(dt);
+ }
+ }
+ }
}
- }
- if (removed) {
- dt = get_deptype (depinfo, "iprovide");
- if (dt)
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_addu (&removedp, service);
- for (di = deptree; di; di = di->next) {
- for (dt = di->depends; dt; dt = dt->next)
- rc_strlist_delete (&dt->services, depinfo->service);
- }
- di = depinfo->next;
- depinfo->next = NULL;
- rc_deptree_free (depinfo);
- depinfo = di;
- } else {
- last_depinfo = depinfo;
- depinfo = depinfo->next;
- }
- }
-
free (nosys);
}
- /* Phase 3 - add our providors to the tree */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- if ((deptype = get_deptype (depinfo, "iprovide")))
- STRLIST_FOREACH (deptype->services, service, i)
- {
- for (di = deptree; di; di = di->next)
- {
- last_depinfo = di;
- if (strcmp (di->service, service) == 0)
+ /* Phase 3 - add our providers to the tree */
+ providers = xmalloc(sizeof(*providers));
+ STAILQ_INIT(providers);
+ STAILQ_FOREACH(depinfo, deptree, entries)
+ if ((deptype = get_deptype(depinfo, "iprovide")))
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ STAILQ_FOREACH(di, providers, entries)
+ if (strcmp(di->service, s->value) == 0)
break;
- }
- if (! di)
- {
- last_depinfo->next = xzalloc (sizeof (*last_depinfo->next));
- di = last_depinfo->next;
- di->service = xstrdup (service);
+ if (! di) {
+ di = xmalloc(sizeof(*di));
+ STAILQ_INIT(&di->depends);
+ di->service = xstrdup(s->value);
+ STAILQ_INSERT_TAIL(providers, di, entries);
}
}
- }
+ STAILQ_CONCAT(deptree, providers);
+ free(providers);
/* Phase 4 - backreference our depends */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- for (i = 0; deppairs[i].depend; i++)
- {
- deptype = get_deptype (depinfo, deppairs[i].depend);
+ STAILQ_FOREACH(depinfo, deptree, entries)
+ for (i = 0; deppairs[i].depend; i++) {
+ deptype = get_deptype(depinfo, deppairs[i].depend);
if (! deptype)
continue;
-
- STRLIST_FOREACH (deptype->services, service, j)
- {
- di = get_depinfo (deptree, service);
- if (! di)
- {
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ di = get_depinfo(deptree, s->value);
+ if (! di) {
if (strcmp (deptype->type, "ineed") == 0)
- {
- bool removed = false;
- STRLIST_FOREACH (removedp, line, k) {
- if (strcmp (line, service) == 0) {
- removed = true;
- break;
- }
- }
- if (! removed)
- fprintf (stderr,
- "Service `%s' needs non existant service `%s'\n",
- depinfo->service, service);
- }
+ fprintf (stderr,
+ "Service `%s' needs non"
+ " existant service `%s'\n",
+ depinfo->service, s->value);
continue;
}
- /* Add our deptype now */
- last_deptype = NULL;
- for (dt = di->depends; dt; dt = dt->next)
- {
- last_deptype = dt;
- if (strcmp (dt->type, deppairs[i].addto) == 0)
- break;
+ dt = get_deptype(di, deppairs[i].addto);
+ if (! dt) {
+ dt = xmalloc(sizeof(*dt));
+ dt->type = xstrdup(deppairs[i].addto);
+ dt->services = rc_stringlist_new();
+ STAILQ_INSERT_TAIL(&di->depends, dt, entries);
}
- if (! dt)
- {
- if (! last_deptype)
- {
- di->depends = xzalloc (sizeof (*di->depends));
- dt = di->depends;
- }
- else
- {
- last_deptype->next = xzalloc (sizeof (*last_deptype->next));
- dt = last_deptype->next;
- }
- dt->type = xstrdup (deppairs[i].addto);
- }
-
- already_added = false;
- STRLIST_FOREACH (dt->services, service, k)
- if (strcmp (service, depinfo->service) == 0)
- {
- already_added = true;
- break;
- }
-
- if (! already_added)
- rc_strlist_addsort (&dt->services, depinfo->service);
+ rc_stringlist_add(dt->services, depinfo->service);
}
}
- }
/* Phase 5 - save to disk
Now that we're purely in C, do we need to keep a shell parseable file?
@@ -1021,49 +905,47 @@ next:
This works and should be entirely shell parseable provided that depend
names don't have any non shell variable characters in
*/
- if ((fp = fopen (RC_DEPTREE, "w"))) {
+ if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) {
i = 0;
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- fprintf (fp, "depinfo_%zu_service='%s'\n",
- i, depinfo->service);
- for (deptype = depinfo->depends; deptype; deptype = deptype->next)
- {
+ STAILQ_FOREACH(depinfo, deptree, entries) {
+ fprintf(fp, "depinfo_%zu_service='%s'\n",
+ i, depinfo->service);
+ STAILQ_FOREACH(deptype, &depinfo->depends, entries) {
k = 0;
- STRLIST_FOREACH (deptype->services, service, j)
- {
- fprintf (fp,
- "depinfo_%zu_%s_%zu='%s'\n",
- i,
- deptype->type,
- k, service);
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ fprintf(fp,
+ "depinfo_%zu_%s_%zu='%s'\n",
+ i, deptype->type, k, s->value);
k++;
}
}
i++;
}
- fclose (fp);
+ fclose(fp);
} else {
- fprintf (stderr, "fopen `%s': %s\n", RC_DEPTREE, strerror (errno));
+ fprintf(stderr, "fopen `%s': %s\n",
+ RC_DEPTREE_CACHE, strerror(errno));
retval = false;
}
/* Save our external config files to disk */
- if (config) {
- if ((fp = fopen (RC_DEPCONFIG, "w"))) {
- STRLIST_FOREACH (config, service, i)
- fprintf (fp, "%s\n", service);
- fclose (fp);
+ if (TAILQ_FIRST(config)) {
+ if ((fp = fopen(RC_DEPCONFIG, "w"))) {
+ TAILQ_FOREACH(s, config, entries)
+ fprintf (fp, "%s\n", s->value);
+ fclose(fp);
} else {
- fprintf (stderr, "fopen `%s': %s\n", RC_DEPCONFIG, strerror (errno));
+ fprintf(stderr, "fopen `%s': %s\n",
+ RC_DEPCONFIG, strerror(errno));
retval = false;
}
- rc_strlist_free (config);
+ rc_stringlist_free (config);
+ } else {
+ unlink(RC_DEPCONFIG);
}
- rc_strlist_free (removedp);
- rc_deptree_free (deptree);
+ rc_deptree_free(deptree);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_deptree_update)