aboutsummaryrefslogtreecommitdiff
path: root/src/librc-depend.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/librc-depend.c')
-rw-r--r--src/librc-depend.c1458
1 files changed, 734 insertions, 724 deletions
diff --git a/src/librc-depend.c b/src/librc-depend.c
index 44a572ef..c8dfd02a 100644
--- a/src/librc-depend.c
+++ b/src/librc-depend.c
@@ -8,231 +8,232 @@
#define GENDEP RC_LIBDIR "/sh/gendepends.sh"
+static const char *bootlevel = NULL;
+
/* We use this so we can pass our char array through many functions */
struct lhead
{
- char **list;
+ char **list;
};
static char *get_shell_value (char *string)
{
- char *p = string;
- char *e;
+ char *p = string;
+ char *e;
- if (! string)
- return (NULL);
+ if (! string)
+ return (NULL);
- if (*p == '\'')
- p++;
+ if (*p == '\'')
+ p++;
- e = p + strlen (p) - 1;
- if (*e == '\n')
- *e-- = 0;
- if (*e == '\'')
- *e-- = 0;
+ e = p + strlen (p) - 1;
+ if (*e == '\n')
+ *e-- = 0;
+ if (*e == '\'')
+ *e-- = 0;
- if (*p != 0)
- return p;
+ if (*p != 0)
+ return p;
- return (NULL);
+ return (NULL);
}
void rc_free_deptree (rc_depinfo_t *deptree)
{
- rc_depinfo_t *di = deptree;
- while (di)
- {
- rc_depinfo_t *dip = di->next;
- rc_deptype_t *dt = di->depends;
- free (di->service);
- while (dt)
- {
- rc_deptype_t *dtp = dt->next;
- free (dt->type);
- rc_strlist_free (dt->services);
- free (dt);
- dt = dtp;
- }
- free (di);
- di = dip;
- }
+ rc_depinfo_t *di = deptree;
+ while (di)
+ {
+ rc_depinfo_t *dip = di->next;
+ rc_deptype_t *dt = di->depends;
+ free (di->service);
+ while (dt)
+ {
+ rc_deptype_t *dtp = dt->next;
+ free (dt->type);
+ rc_strlist_free (dt->services);
+ free (dt);
+ dt = dtp;
+ }
+ free (di);
+ di = dip;
+ }
}
librc_hidden_def(rc_free_deptree)
rc_depinfo_t *rc_load_deptree (void)
{
- FILE *fp;
- rc_depinfo_t *deptree = NULL;
- rc_depinfo_t *depinfo = NULL;
- rc_deptype_t *deptype = NULL;
- char buffer [RC_LINEBUFFER];
- char *type;
- char *p;
- char *e;
- int i;
-
- /* Update our deptree, but only if we need too */
- rc_update_deptree (false);
-
- if (! (fp = fopen (RC_DEPTREE, "r")))
- return (NULL);
-
- while (fgets (buffer, RC_LINEBUFFER, fp))
- {
- p = buffer;
- e = strsep (&p, "_");
- if (! e || strcmp (e, "depinfo") != 0)
- continue;
-
- e = strsep (&p, "_");
- if (! e || sscanf (e, "%d", &i) != 1)
- continue;
-
- if (! (type = strsep (&p, "_=")))
- continue;
-
- if (strcmp (type, "service") == 0)
- {
- /* Sanity */
- e = get_shell_value (p);
- if (! e || strlen (e) == 0)
- continue;
-
- if (! deptree)
- {
- deptree = rc_xmalloc (sizeof (rc_depinfo_t));
- depinfo = deptree;
- }
- else
- {
- depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
- depinfo = depinfo->next;
- }
- memset (depinfo, 0, sizeof (rc_depinfo_t));
- depinfo->service = rc_xstrdup (e);
- deptype = NULL;
- continue;
- }
-
- e = strsep (&p, "=");
- if (! e || sscanf (e, "%d", &i) != 1)
- continue;
-
- /* Sanity */
- e = get_shell_value (p);
- if (! e || strlen (e) == 0)
- continue;
-
- if (! deptype)
- {
- depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t));
- deptype = depinfo->depends;
- memset (deptype, 0, sizeof (rc_deptype_t));
- }
- else
- if (strcmp (deptype->type, type) != 0)
- {
- deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
- deptype = deptype->next;
- memset (deptype, 0, sizeof (rc_deptype_t));
- }
-
- if (! deptype->type)
- deptype->type = rc_xstrdup (type);
-
- deptype->services = rc_strlist_addsort (deptype->services, e);
- }
- fclose (fp);
-
- return (deptree);
+ FILE *fp;
+ rc_depinfo_t *deptree = NULL;
+ rc_depinfo_t *depinfo = NULL;
+ rc_deptype_t *deptype = NULL;
+ char buffer [RC_LINEBUFFER];
+ char *type;
+ char *p;
+ char *e;
+ int i;
+
+ /* Update our deptree, but only if we need too */
+ rc_update_deptree (false);
+
+ if (! (fp = fopen (RC_DEPTREE, "r")))
+ return (NULL);
+
+ while (fgets (buffer, RC_LINEBUFFER, fp))
+ {
+ p = buffer;
+ e = strsep (&p, "_");
+ if (! e || strcmp (e, "depinfo") != 0)
+ continue;
+
+ e = strsep (&p, "_");
+ if (! e || sscanf (e, "%d", &i) != 1)
+ continue;
+
+ if (! (type = strsep (&p, "_=")))
+ continue;
+
+ if (strcmp (type, "service") == 0)
+ {
+ /* Sanity */
+ e = get_shell_value (p);
+ if (! e || strlen (e) == 0)
+ continue;
+
+ if (! deptree)
+ {
+ deptree = rc_xmalloc (sizeof (rc_depinfo_t));
+ depinfo = deptree;
+ }
+ else
+ {
+ depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
+ depinfo = depinfo->next;
+ }
+ memset (depinfo, 0, sizeof (rc_depinfo_t));
+ depinfo->service = rc_xstrdup (e);
+ deptype = NULL;
+ continue;
+ }
+
+ e = strsep (&p, "=");
+ if (! e || sscanf (e, "%d", &i) != 1)
+ continue;
+
+ /* Sanity */
+ e = get_shell_value (p);
+ if (! e || strlen (e) == 0)
+ continue;
+
+ if (! deptype)
+ {
+ depinfo->depends = rc_xmalloc (sizeof (rc_deptype_t));
+ deptype = depinfo->depends;
+ memset (deptype, 0, sizeof (rc_deptype_t));
+ }
+ else
+ if (strcmp (deptype->type, type) != 0)
+ {
+ deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
+ deptype = deptype->next;
+ memset (deptype, 0, sizeof (rc_deptype_t));
+ }
+
+ if (! deptype->type)
+ deptype->type = rc_xstrdup (type);
+
+ deptype->services = rc_strlist_addsort (deptype->services, e);
+ }
+ fclose (fp);
+
+ return (deptree);
}
librc_hidden_def(rc_load_deptree)
rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service)
{
- rc_depinfo_t *di;
+ rc_depinfo_t *di;
- if (! deptree || ! service)
- return (NULL);
+ if (! deptree || ! service)
+ return (NULL);
- for (di = deptree; di; di = di->next)
- if (strcmp (di->service, service) == 0)
- return (di);
+ for (di = deptree; di; di = di->next)
+ if (strcmp (di->service, service) == 0)
+ return (di);
- return (NULL);
+ return (NULL);
}
librc_hidden_def(rc_get_depinfo)
rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type)
{
- rc_deptype_t *dt;
+ rc_deptype_t *dt;
- if (! depinfo || !type)
- return (NULL);
+ if (! depinfo || !type)
+ return (NULL);
- for (dt = depinfo->depends; dt; dt = dt->next)
- 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);
}
librc_hidden_def(rc_get_deptype)
static bool valid_service (const char *runlevel, const char *service)
{
- return ((strcmp (runlevel, RC_LEVEL_BOOT) != 0 &&
- rc_service_in_runlevel (service, RC_LEVEL_BOOT)) ||
- rc_service_in_runlevel (service, runlevel) ||
- rc_service_state (service, rc_service_coldplugged) ||
- rc_service_state (service, rc_service_started));
+ return ((strcmp (runlevel, bootlevel) != 0 &&
+ rc_service_in_runlevel (service, bootlevel)) ||
+ rc_service_in_runlevel (service, runlevel) ||
+ rc_service_state (service, rc_service_coldplugged) ||
+ rc_service_state (service, rc_service_started));
}
static bool get_provided1 (const char *runlevel, struct lhead *providers,
- rc_deptype_t *deptype,
- const char *level, bool coldplugged,
+ rc_deptype_t *deptype,
+ const char *level, bool coldplugged,
rc_service_state_t state)
{
- char *service;
- int i;
- bool retval = false;
- char *bootlevel = getenv ("RC_BOOTLEVEL");
-
- STRLIST_FOREACH (deptype->services, service, i)
- {
- bool ok = true;
- if (level)
- ok = rc_service_in_runlevel (service, level);
- else if (coldplugged)
- ok = (rc_service_state (service, rc_service_coldplugged) &&
- ! rc_service_in_runlevel (service, runlevel) &&
- ! rc_service_in_runlevel (service, bootlevel));
-
- if (! ok)
- continue;
-
- switch (state) {
- case rc_service_started:
- ok = rc_service_state (service, state);
- break;
- case rc_service_inactive:
- case rc_service_starting:
- case rc_service_stopping:
- ok = (rc_service_state (service, rc_service_starting) ||
- rc_service_state (service, rc_service_stopping) ||
- rc_service_state (service, rc_service_inactive));
- break;
- default:
- break;
- }
-
- if (! ok)
- continue;
-
- retval = true;
- providers->list = rc_strlist_add (providers->list, service);
- }
-
- return (retval);
+ char *service;
+ int i;
+ bool retval = false;
+
+ STRLIST_FOREACH (deptype->services, service, i)
+ {
+ bool ok = true;
+ if (level)
+ ok = rc_service_in_runlevel (service, level);
+ else if (coldplugged)
+ ok = (rc_service_state (service, rc_service_coldplugged) &&
+ ! rc_service_in_runlevel (service, runlevel) &&
+ ! rc_service_in_runlevel (service, bootlevel));
+
+ if (! ok)
+ continue;
+
+ switch (state) {
+ case rc_service_started:
+ ok = rc_service_state (service, state);
+ break;
+ case rc_service_inactive:
+ case rc_service_starting:
+ case rc_service_stopping:
+ ok = (rc_service_state (service, rc_service_starting) ||
+ rc_service_state (service, rc_service_stopping) ||
+ rc_service_state (service, rc_service_inactive));
+ break;
+ default:
+ break;
+ }
+
+ if (! ok)
+ continue;
+
+ retval = true;
+ providers->list = rc_strlist_add (providers->list, service);
+ }
+
+ return (retval);
}
/* Work out if a service is provided by another service.
@@ -245,345 +246,354 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers,
provided dependancy can change depending on runlevel state.
*/
static char **get_provided (rc_depinfo_t *deptree, rc_depinfo_t *depinfo,
- const char *runlevel, int options)
+ const char *runlevel, int options)
{
- rc_deptype_t *dt;
- struct lhead providers;
- char *service;
- int i;
- char *bootlevel;
-
- if (! deptree || ! depinfo)
- return (NULL);
- if (rc_service_exists (depinfo->service))
- return (NULL);
-
- dt = rc_get_deptype (depinfo, "providedby");
- if (! dt)
- return (NULL);
-
- memset (&providers, 0, sizeof (struct lhead));
- /* 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)
- providers.list = rc_strlist_add (providers.list, service);
-
- return (providers.list);
- }
-
- /* If we're strict, then only use what we have in our runlevel */
- if (options & RC_DEP_STRICT)
- {
- STRLIST_FOREACH (dt->services, service, i)
- if (rc_service_in_runlevel (service, runlevel))
- providers.list = rc_strlist_add (providers.list, service);
-
- if (providers.list)
- return (providers.list);
- }
-
- /* OK, we're not strict or there were no services in our runlevel.
- This is now where the logic gets a little fuzzy :)
- If there is >1 running service then we return NULL.
- We do this so we don't hang around waiting for inactive services and
- our need has already been satisfied as it's not strict.
- We apply this to 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; \
-
- /* Anything in the runlevel has to come first */
- 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);
+ rc_deptype_t *dt;
+ struct lhead providers;
+ char *service;
+ int i;
+
+ if (! deptree || ! depinfo)
+ return (NULL);
+ if (rc_service_exists (depinfo->service))
+ return (NULL);
+
+ dt = rc_get_deptype (depinfo, "providedby");
+ if (! dt)
+ return (NULL);
+
+ memset (&providers, 0, sizeof (struct lhead));
+ /* 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)
+ providers.list = rc_strlist_add (providers.list, service);
+
+ return (providers.list);
+ }
- /* Check coldplugged services */
- 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 we're strict, then only use what we have in our runlevel
+ * and bootlevel */
+ if (options & RC_DEP_STRICT)
+ {
+ STRLIST_FOREACH (dt->services, service, i)
+ if (rc_service_in_runlevel (service, runlevel) ||
+ rc_service_in_runlevel (service, bootlevel))
+ providers.list = rc_strlist_add (providers.list, service);
+
+ if (providers.list)
+ return (providers.list);
+ }
- /* Check bootlevel if we're not in it */
- bootlevel = getenv ("RC_BOOTLEVEL");
- if (bootlevel && strcmp (runlevel, bootlevel) != 0)
- {
- 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);
+ /* OK, we're not strict or there were no services in our runlevel.
+ This is now where the logic gets a little fuzzy :)
+ If there is >1 running service then we return NULL.
+ We do this so we don't hang around waiting for inactive services and
+ our need has already been satisfied as it's not strict.
+ We apply this to 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; \
+
+ /* Anything in the runlevel has to come first */
+ 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);
+
+ /* Check coldplugged services */
+ 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);
+
+ /* 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))
+ { DO }
+ if (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_starting))
+ return (providers.list);
}
- /* Check coldplugged services */
- if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_stopped))
+ /* Check coldplugged services */
+ if (get_provided1 (runlevel, &providers, dt, NULL, true, rc_service_stopped))
- /* Check manually 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);
+ /* Check manually 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);
- /* Nothing started then. OK, lets get the stopped services */
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
- return (providers.list);
+ /* Nothing started then. OK, lets get the stopped services */
+ if (get_provided1 (runlevel, &providers, dt, runlevel, false, rc_service_stopped))
+ return (providers.list);
- if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
- && (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_stopped)))
- return (providers.list);
+ if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
+ && (get_provided1 (runlevel, &providers, dt, bootlevel, false, rc_service_stopped)))
+ return (providers.list);
- /* Still nothing? OK, list all services */
- STRLIST_FOREACH (dt->services, service, i)
- providers.list = rc_strlist_add (providers.list, service);
+ /* Still nothing? OK, list all services */
+ STRLIST_FOREACH (dt->services, service, i)
+ providers.list = rc_strlist_add (providers.list, service);
- return (providers.list);
+ return (providers.list);
}
static void visit_service (rc_depinfo_t *deptree, char **types,
- struct lhead *sorted, struct lhead *visited,
- rc_depinfo_t *depinfo,
- const char *runlevel, int options)
+ struct lhead *sorted, struct lhead *visited,
+ rc_depinfo_t *depinfo,
+ const char *runlevel, int options)
{
- int i, j, k;
- char *lp, *item;
- char *service;
- rc_depinfo_t *di;
- rc_deptype_t *dt;
- char **provides;
- char *svcname;
-
- if (! deptree || !sorted || !visited || !depinfo)
- return;
-
- /* Check if we have already visited this service or not */
- STRLIST_FOREACH (visited->list, item, i)
- if (strcmp (item, depinfo->service) == 0)
- return;
-
- /* Add ourselves as a visited service */
- visited->list = rc_strlist_add (visited->list, depinfo->service);
-
- STRLIST_FOREACH (types, item, i)
- {
- if ((dt = rc_get_deptype (depinfo, item)))
- {
- STRLIST_FOREACH (dt->services, service, j)
- {
- if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0)
- {
- sorted->list = rc_strlist_add (sorted->list, service);
- continue;
- }
-
- di = rc_get_depinfo (deptree, service);
- if ((provides = get_provided (deptree, di, runlevel, options)))
- {
- STRLIST_FOREACH (provides, lp, k)
- {
- di = rc_get_depinfo (deptree, lp);
- if (di && (strcmp (item, "ineed") == 0 ||
- valid_service (runlevel, di->service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- }
- rc_strlist_free (provides);
- }
- else
- if (di && (strcmp (item, "ineed") == 0 ||
- valid_service (runlevel, service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- }
- }
- }
-
- /* Now visit the stuff we provide for */
- if (options & RC_DEP_TRACE && (dt = rc_get_deptype (depinfo, "iprovide")))
- {
- STRLIST_FOREACH (dt->services, service, i)
- {
- if ((di = rc_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);
- }
- }
- }
-
- /* 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 (! rc_get_deptype (depinfo, "providedby"))
- sorted->list = rc_strlist_add (sorted->list, depinfo->service);
+ int i, j, k;
+ char *lp, *item;
+ char *service;
+ rc_depinfo_t *di;
+ rc_deptype_t *dt;
+ char **provides;
+ char *svcname;
+
+ if (! deptree || !sorted || !visited || !depinfo)
+ return;
+
+ /* Check if we have already visited this service or not */
+ STRLIST_FOREACH (visited->list, item, i)
+ if (strcmp (item, depinfo->service) == 0)
+ return;
+
+ /* Add ourselves as a visited service */
+ visited->list = rc_strlist_add (visited->list, depinfo->service);
+
+ STRLIST_FOREACH (types, item, i)
+ {
+ if ((dt = rc_get_deptype (depinfo, item)))
+ {
+ STRLIST_FOREACH (dt->services, service, j)
+ {
+ if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0)
+ {
+ sorted->list = rc_strlist_add (sorted->list, service);
+ continue;
+ }
+
+ di = rc_get_depinfo (deptree, service);
+ if ((provides = get_provided (deptree, di, runlevel, options)))
+ {
+ STRLIST_FOREACH (provides, lp, k)
+ {
+ di = rc_get_depinfo (deptree, lp);
+ if (di && (strcmp (item, "ineed") == 0 ||
+ valid_service (runlevel, di->service)))
+ visit_service (deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
+ }
+ rc_strlist_free (provides);
+ }
+ else
+ if (di && (strcmp (item, "ineed") == 0 ||
+ valid_service (runlevel, service)))
+ visit_service (deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
+ }
+ }
+ }
+
+ /* Now visit the stuff we provide for */
+ if (options & RC_DEP_TRACE && (dt = rc_get_deptype (depinfo, "iprovide")))
+ {
+ STRLIST_FOREACH (dt->services, service, i)
+ {
+ if ((di = rc_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);
+ }
+ }
+ }
+
+ /* 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 (! rc_get_deptype (depinfo, "providedby"))
+ sorted->list = rc_strlist_add (sorted->list, depinfo->service);
}
char **rc_get_depends (rc_depinfo_t *deptree,
- char **types, char **services,
- const char *runlevel, int options)
+ char **types, char **services,
+ const char *runlevel, int options)
{
- struct lhead sorted;
- struct lhead visited;
- rc_depinfo_t *di;
- char *service;
- int i;
-
- if (! deptree || ! types || ! services)
- return (NULL);
-
- memset (&sorted, 0, sizeof (struct lhead));
- memset (&visited, 0, sizeof (struct lhead));
-
- STRLIST_FOREACH (services, service, i)
- {
- di = rc_get_depinfo (deptree, service);
- visit_service (deptree, types, &sorted, &visited, di, runlevel, options);
- }
-
- rc_strlist_free (visited.list);
- return (sorted.list);
+ struct lhead sorted;
+ struct lhead visited;
+ rc_depinfo_t *di;
+ char *service;
+ int i;
+
+ if (! deptree || ! types || ! services)
+ return (NULL);
+
+ memset (&sorted, 0, sizeof (struct lhead));
+ memset (&visited, 0, sizeof (struct lhead));
+
+ bootlevel = getenv ("RC_BOOTLEVEL");
+ if (! bootlevel)
+ bootlevel = RC_LEVEL_BOOT;
+
+ STRLIST_FOREACH (services, service, i)
+ {
+ di = rc_get_depinfo (deptree, service);
+ visit_service (deptree, types, &sorted, &visited, di, runlevel, options);
+ }
+
+ rc_strlist_free (visited.list);
+ return (sorted.list);
}
librc_hidden_def(rc_get_depends)
char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel,
- int options)
+ int options)
{
- char **list = NULL;
- char **types = NULL;
- char **services = NULL;
- bool reverse = false;
-
- if (! runlevel)
- return (NULL);
-
- /* When shutting down, list all running services */
- if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
- strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
- strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
- {
- list = rc_ls_dir (list, RC_SVCDIR_STARTING, RC_LS_INITD);
- list = rc_ls_dir (list, RC_SVCDIR_INACTIVE, RC_LS_INITD);
- list = rc_ls_dir (list, RC_SVCDIR_STARTED, RC_LS_INITD);
- reverse = true;
- }
- else
- {
- list = rc_services_in_runlevel (runlevel);
-
- /* Add coldplugged services */
- list = rc_ls_dir (list, RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
-
- /* If we're not the boot runlevel then add that too */
- if (strcmp (runlevel, RC_LEVEL_BOOT) != 0)
- {
- char *path = rc_strcatpaths (RC_RUNLEVELDIR, RC_LEVEL_BOOT,
- (char *) NULL);
- list = rc_ls_dir (list, path, RC_LS_INITD);
- free (path);
- }
- }
-
- /* Now we have our lists, we need to pull in any dependencies
- and order them */
- types = rc_strlist_add (NULL, "ineed");
- types = rc_strlist_add (types, "iuse");
- types = rc_strlist_add (types, "iafter");
- services = rc_get_depends (deptree, types, list, runlevel,
- RC_DEP_STRICT | RC_DEP_TRACE | options);
- rc_strlist_free (list);
- rc_strlist_free (types);
-
- if (reverse)
- rc_strlist_reverse (services);
-
- return (services);
+ char **list = NULL;
+ char **types = NULL;
+ char **services = NULL;
+ bool reverse = false;
+
+ if (! runlevel)
+ return (NULL);
+
+ bootlevel = getenv ("RC_BOOTLEVEL");
+ if (! bootlevel)
+ bootlevel = RC_LEVEL_BOOT;
+
+ /* When shutting down, list all running services */
+ if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
+ strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
+ strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
+ {
+ list = rc_ls_dir (list, RC_SVCDIR_STARTING, RC_LS_INITD);
+ list = rc_ls_dir (list, RC_SVCDIR_INACTIVE, RC_LS_INITD);
+ list = rc_ls_dir (list, RC_SVCDIR_STARTED, RC_LS_INITD);
+ reverse = true;
+ }
+ else
+ {
+ list = rc_services_in_runlevel (runlevel);
+
+ /* Add coldplugged services */
+ list = rc_ls_dir (list, RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
+
+
+ /* If we're not the boot runlevel then add that too */
+ if (strcmp (runlevel, bootlevel) != 0)
+ {
+ char *path = rc_strcatpaths (RC_RUNLEVELDIR, bootlevel,
+ (char *) NULL);
+ list = rc_ls_dir (list, path, RC_LS_INITD);
+ free (path);
+ }
+ }
+
+ /* Now we have our lists, we need to pull in any dependencies
+ and order them */
+ types = rc_strlist_add (NULL, "ineed");
+ types = rc_strlist_add (types, "iuse");
+ types = rc_strlist_add (types, "iafter");
+ services = rc_get_depends (deptree, types, list, runlevel,
+ RC_DEP_STRICT | RC_DEP_TRACE | options);
+ rc_strlist_free (list);
+ rc_strlist_free (types);
+
+ if (reverse)
+ rc_strlist_reverse (services);
+
+ return (services);
}
librc_hidden_def(rc_order_services)
static bool is_newer_than (const char *file, const char *target)
{
- struct stat buf;
- time_t mtime;
-
- if (stat (file, &buf) != 0 || buf.st_size == 0)
- return (false);
- mtime = buf.st_mtime;
-
- /* Of course we are newever than targets that don't exist
- Such as broken symlinks */
- if (stat (target, &buf) != 0)
- return (true);
-
- if (mtime < buf.st_mtime)
- return (false);
-
- if (rc_is_dir (target))
- {
- char **targets = rc_ls_dir (NULL, target, 0);
- char *t;
- int i;
- bool newer = true;
- STRLIST_FOREACH (targets, t, i)
- {
- char *path = rc_strcatpaths (target, t, (char *) NULL);
- newer = is_newer_than (file, path);
- free (path);
- if (! newer)
- break;
- }
- rc_strlist_free (targets);
- return (newer);
- }
-
- return (true);
+ struct stat buf;
+ time_t mtime;
+
+ if (stat (file, &buf) != 0 || buf.st_size == 0)
+ return (false);
+ mtime = buf.st_mtime;
+
+ /* Of course we are newever than targets that don't exist
+ Such as broken symlinks */
+ if (stat (target, &buf) != 0)
+ return (true);
+
+ if (mtime < buf.st_mtime)
+ return (false);
+
+ if (rc_is_dir (target))
+ {
+ char **targets = rc_ls_dir (NULL, target, 0);
+ char *t;
+ int i;
+ bool newer = true;
+ STRLIST_FOREACH (targets, t, i)
+ {
+ char *path = rc_strcatpaths (target, t, (char *) NULL);
+ newer = is_newer_than (file, path);
+ free (path);
+ if (! newer)
+ break;
+ }
+ rc_strlist_free (targets);
+ return (newer);
+ }
+
+ return (true);
}
typedef struct deppair
{
- const char *depend;
- const char *addto;
+ const char *depend;
+ const char *addto;
} deppair_t;
static const deppair_t deppairs[] = {
- { "ineed", "needsme" },
- { "iuse", "usesme" },
- { "iafter", "ibefore" },
- { "ibefore", "iafter" },
- { "iprovide", "providedby" },
- { NULL, NULL }
+ { "ineed", "needsme" },
+ { "iuse", "usesme" },
+ { "iafter", "ibefore" },
+ { "ibefore", "iafter" },
+ { "iprovide", "providedby" },
+ { NULL, NULL }
};
static const char *depdirs[] =
{
- RC_SVCDIR "starting",
- RC_SVCDIR "started",
- RC_SVCDIR "stopping",
- RC_SVCDIR "inactive",
- RC_SVCDIR "wasinactive",
- RC_SVCDIR "failed",
- RC_SVCDIR "coldplugged",
- RC_SVCDIR "daemons",
- RC_SVCDIR "options",
- RC_SVCDIR "exclusive",
- RC_SVCDIR "scheduled",
- NULL
+ RC_SVCDIR "starting",
+ RC_SVCDIR "started",
+ RC_SVCDIR "stopping",
+ RC_SVCDIR "inactive",
+ RC_SVCDIR "wasinactive",
+ RC_SVCDIR "failed",
+ RC_SVCDIR "coldplugged",
+ RC_SVCDIR "daemons",
+ RC_SVCDIR "options",
+ RC_SVCDIR "exclusive",
+ RC_SVCDIR "scheduled",
+ NULL
};
/* This is a 5 phase operation
@@ -596,251 +606,251 @@ static const char *depdirs[] =
*/
int rc_update_deptree (bool force)
{
- char *depends;
- char *service;
- char *type;
- char *depend;
- int retval = 0;
- FILE *fp;
- rc_depinfo_t *deptree;
- rc_depinfo_t *depinfo;
- rc_depinfo_t *di;
- rc_depinfo_t *last_depinfo = NULL;
- rc_deptype_t *deptype;
- rc_deptype_t *dt;
- rc_deptype_t *last_deptype = NULL;
- char buffer[RC_LINEBUFFER];
- int len;
- int i;
- int j;
- int k;
- bool already_added;
-
- /* Create base directories if needed */
- for (i = 0; depdirs[i]; i++)
- if (! rc_is_dir (depdirs[i]))
- if (mkdir (depdirs[i], 0755) != 0)
- eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno));
-
- if (! force)
- if (is_newer_than (RC_DEPTREE, RC_INITDIR) &&
- is_newer_than (RC_DEPTREE, RC_CONFDIR) &&
- is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
- return 0;
-
- ebegin ("Caching service dependencies");
-
- /* 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);
-
- /* Phase 1 */
- if (! (fp = popen (GENDEP, "r")))
- eerrorx ("popen: %s", strerror (errno));
-
- deptree = rc_xmalloc (sizeof (rc_depinfo_t));
- memset (deptree, 0, sizeof (rc_depinfo_t));
- memset (buffer, 0, RC_LINEBUFFER);
-
- /* Phase 2 */
- while (fgets (buffer, RC_LINEBUFFER, fp))
- {
- /* Trim the newline */
- if (buffer[strlen (buffer) - 1] == '\n')
- buffer[strlen(buffer) -1] = 0;
-
- depends = buffer;
- service = strsep (&depends, " ");
- if (! service)
- continue;
- 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->service)
- depinfo = last_depinfo;
- else
- {
- last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
- depinfo = last_depinfo->next;
- }
- memset (depinfo, 0, sizeof (rc_depinfo_t));
- depinfo->service = rc_xstrdup (service);
- }
-
- /* We may not have any depends */
- if (! type || ! depends)
- continue;
-
- 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 = rc_xmalloc (sizeof (rc_deptype_t));
- deptype = depinfo->depends;
- }
- else
- {
- last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
- deptype = last_deptype->next;
- }
- memset (deptype, 0, sizeof (rc_deptype_t));
- deptype->type = rc_xstrdup (type);
- }
-
- /* Now add each depend to our type.
- We do this individually so we handle multiple spaces gracefully */
- while ((depend = strsep (&depends, " ")))
- {
- if (depend[0] == 0)
- continue;
-
- /* .sh files are not init scripts */
- len = strlen (depend);
- if (len > 2 &&
- depend[len - 3] == '.' &&
- depend[len - 2] == 's' &&
- depend[len - 1] == 'h')
- continue;
-
- deptype->services = rc_strlist_addsort (deptype->services, depend);
- }
-
- }
- pclose (fp);
-
- /* Phase 3 - add our providors to the tree */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- if ((deptype = rc_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)
- break;
- }
- if (! di)
- {
- last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
- di = last_depinfo->next;
- memset (di, 0, sizeof (rc_depinfo_t));
- di->service = rc_xstrdup (service);
- }
- }
- }
-
- /* Phase 4 - backreference our depends */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- for (i = 0; deppairs[i].depend; i++)
- {
- deptype = rc_get_deptype (depinfo, deppairs[i].depend);
- if (! deptype)
- continue;
-
- STRLIST_FOREACH (deptype->services, service, j)
- {
- di = rc_get_depinfo (deptree, service);
- if (! di)
- {
- if (strcmp (deptype->type, "ineed") == 0)
- {
- eerror ("Service `%s' needs non existant service `%s'",
- depinfo->service, service);
- retval = -1;
- }
- 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;
- }
- if (! dt)
- {
- if (! last_deptype)
- {
- di->depends = rc_xmalloc (sizeof (rc_deptype_t));
- dt = di->depends;
- }
- else
- {
- last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
- dt = last_deptype->next;
- }
- memset (dt, 0, sizeof (rc_deptype_t));
- dt->type = rc_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)
- dt->services = rc_strlist_addsort (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?
- I think yes as then it stays human readable
- This works and should be entirely shell parseable provided that depend
- names don't have any non shell variable characters in
- */
- if (! (fp = fopen (RC_DEPTREE, "w")))
- eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno));
- else
- {
- i = 0;
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- fprintf (fp, "depinfo_%d_service='%s'\n", i, depinfo->service);
- for (deptype = depinfo->depends; deptype; deptype = deptype->next)
- {
- k = 0;
- STRLIST_FOREACH (deptype->services, service, j)
- {
- fprintf (fp, "depinfo_%d_%s_%d='%s'\n", i, deptype->type,
- k, service);
- k++;
- }
- }
- i++;
- }
- fclose (fp);
- }
-
- rc_free_deptree (deptree);
-
- eend (retval, "Failed to update the service dependency tree");
- return (retval);
+ char *depends;
+ char *service;
+ char *type;
+ char *depend;
+ int retval = 0;
+ FILE *fp;
+ rc_depinfo_t *deptree;
+ rc_depinfo_t *depinfo;
+ rc_depinfo_t *di;
+ rc_depinfo_t *last_depinfo = NULL;
+ rc_deptype_t *deptype;
+ rc_deptype_t *dt;
+ rc_deptype_t *last_deptype = NULL;
+ char buffer[RC_LINEBUFFER];
+ int len;
+ int i;
+ int j;
+ int k;
+ bool already_added;
+
+ /* Create base directories if needed */
+ for (i = 0; depdirs[i]; i++)
+ if (! rc_is_dir (depdirs[i]))
+ if (mkdir (depdirs[i], 0755) != 0)
+ eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno));
+
+ if (! force)
+ if (is_newer_than (RC_DEPTREE, RC_INITDIR) &&
+ is_newer_than (RC_DEPTREE, RC_CONFDIR) &&
+ is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
+ return 0;
+
+ ebegin ("Caching service dependencies");
+
+ /* 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);
+
+ /* Phase 1 */
+ if (! (fp = popen (GENDEP, "r")))
+ eerrorx ("popen: %s", strerror (errno));
+
+ deptree = rc_xmalloc (sizeof (rc_depinfo_t));
+ memset (deptree, 0, sizeof (rc_depinfo_t));
+ memset (buffer, 0, RC_LINEBUFFER);
+
+ /* Phase 2 */
+ while (fgets (buffer, RC_LINEBUFFER, fp))
+ {
+ /* Trim the newline */
+ if (buffer[strlen (buffer) - 1] == '\n')
+ buffer[strlen(buffer) -1] = 0;
+
+ depends = buffer;
+ service = strsep (&depends, " ");
+ if (! service)
+ continue;
+ 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->service)
+ depinfo = last_depinfo;
+ else
+ {
+ last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
+ depinfo = last_depinfo->next;
+ }
+ memset (depinfo, 0, sizeof (rc_depinfo_t));
+ depinfo->service = rc_xstrdup (service);
+ }
+
+ /* We may not have any depends */
+ if (! type || ! depends)
+ continue;
+
+ 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 = rc_xmalloc (sizeof (rc_deptype_t));
+ deptype = depinfo->depends;
+ }
+ else
+ {
+ last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
+ deptype = last_deptype->next;
+ }
+ memset (deptype, 0, sizeof (rc_deptype_t));
+ deptype->type = rc_xstrdup (type);
+ }
+
+ /* Now add each depend to our type.
+ We do this individually so we handle multiple spaces gracefully */
+ while ((depend = strsep (&depends, " ")))
+ {
+ if (depend[0] == 0)
+ continue;
+
+ /* .sh files are not init scripts */
+ len = strlen (depend);
+ if (len > 2 &&
+ depend[len - 3] == '.' &&
+ depend[len - 2] == 's' &&
+ depend[len - 1] == 'h')
+ continue;
+
+ deptype->services = rc_strlist_addsort (deptype->services, depend);
+ }
+
+ }
+ pclose (fp);
+
+ /* Phase 3 - add our providors to the tree */
+ for (depinfo = deptree; depinfo; depinfo = depinfo->next)
+ {
+ if ((deptype = rc_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)
+ break;
+ }
+ if (! di)
+ {
+ last_depinfo->next = rc_xmalloc (sizeof (rc_depinfo_t));
+ di = last_depinfo->next;
+ memset (di, 0, sizeof (rc_depinfo_t));
+ di->service = rc_xstrdup (service);
+ }
+ }
+ }
+
+ /* Phase 4 - backreference our depends */
+ for (depinfo = deptree; depinfo; depinfo = depinfo->next)
+ {
+ for (i = 0; deppairs[i].depend; i++)
+ {
+ deptype = rc_get_deptype (depinfo, deppairs[i].depend);
+ if (! deptype)
+ continue;
+
+ STRLIST_FOREACH (deptype->services, service, j)
+ {
+ di = rc_get_depinfo (deptree, service);
+ if (! di)
+ {
+ if (strcmp (deptype->type, "ineed") == 0)
+ {
+ eerror ("Service `%s' needs non existant service `%s'",
+ depinfo->service, service);
+ retval = -1;
+ }
+ 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;
+ }
+ if (! dt)
+ {
+ if (! last_deptype)
+ {
+ di->depends = rc_xmalloc (sizeof (rc_deptype_t));
+ dt = di->depends;
+ }
+ else
+ {
+ last_deptype->next = rc_xmalloc (sizeof (rc_deptype_t));
+ dt = last_deptype->next;
+ }
+ memset (dt, 0, sizeof (rc_deptype_t));
+ dt->type = rc_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)
+ dt->services = rc_strlist_addsort (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?
+ I think yes as then it stays human readable
+ This works and should be entirely shell parseable provided that depend
+ names don't have any non shell variable characters in
+ */
+ if (! (fp = fopen (RC_DEPTREE, "w")))
+ eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno));
+ else
+ {
+ i = 0;
+ for (depinfo = deptree; depinfo; depinfo = depinfo->next)
+ {
+ fprintf (fp, "depinfo_%d_service='%s'\n", i, depinfo->service);
+ for (deptype = depinfo->depends; deptype; deptype = deptype->next)
+ {
+ k = 0;
+ STRLIST_FOREACH (deptype->services, service, j)
+ {
+ fprintf (fp, "depinfo_%d_%s_%d='%s'\n", i, deptype->type,
+ k, service);
+ k++;
+ }
+ }
+ i++;
+ }
+ fclose (fp);
+ }
+
+ rc_free_deptree (deptree);
+
+ eend (retval, "Failed to update the service dependency tree");
+ return (retval);
}
librc_hidden_def(rc_update_deptree)