diff options
author | Roy Marples <roy@marples.name> | 2007-07-21 12:49:51 +0000 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2007-07-21 12:49:51 +0000 |
commit | 6343b488938a9ba4d53252c9021905ead5bf189a (patch) | |
tree | 1dc6a840ccc43f406333aaeb2c7ad85309c0f978 | |
parent | 76f2391ecea775b6d84299620bd1ac18d22b2564 (diff) |
RC_DEPEND_STRICT now controls dependency strictness.
If yes then we only use services in the boot and default runlevels,
regradless of service state.
If no then we take into account coldplugged services and the state
of currently running services.
Fixes #185640.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | conf.d/rc | 6 | ||||
-rw-r--r-- | src/librc-depend.c | 1458 | ||||
-rw-r--r-- | src/rc.c | 27 | ||||
-rw-r--r-- | src/runscript.c | 22 |
5 files changed, 778 insertions, 744 deletions
@@ -1,6 +1,15 @@ # ChangeLog for Gentoo System Intialization ("rc") scripts # Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2 + 21 Jul 2007; Roy Marples <uberlord@gentoo.org>: + + RC_DEPEND_STRICT now controls dependency strictness. + If yes then we only use services in the boot and default runlevels, + regradless of service state. + If no then we take into account coldplugged services and the state + of currently running services. + Fixes #185640. + 15 Jul 2007; Roy Marples <uberlord@gentoo.org>: adsl module now finds the correct exe, #185276 thanks to Marcello Laganà . @@ -22,11 +22,11 @@ RC_QUIET="no" # Do we allow any started service in the runlevel to satisfy the depedency # or do we want all of them regardless of state? For example, if net.eth0 -# and net.eth0 are in the default runlevel then with RC_STRICT_DEPEND="no" +# and net.eth0 are in the default runlevel then with RC_DEPEND_STRICT="no" # both will be started, but services that depend on 'net' will work if either -# one comes up. With RC_STRICT_DEPEND="yes" we would require them both to +# one comes up. With RC_DEPEND_STRICT="yes" we would require them both to # come up. -RC_STRICT_DEPEND="no" +RC_DEPEND_STRICT="no" # Do we allow services to be hotplugged? If not, set to RC_HOTPLUG="no" # NOTE: This does not affect anything hotplug/udev/devd related, just the 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) @@ -464,7 +464,7 @@ static void set_ksoftlevel (const char *runlevel) FILE *fp; if (! runlevel || - strcmp (runlevel, RC_LEVEL_BOOT) == 0 || + strcmp (runlevel, getenv ("RC_BOOTLEVEL")) == 0 || strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) { @@ -644,6 +644,7 @@ static struct option longopts[] = { int main (int argc, char **argv) { char *runlevel = NULL; + const char *bootlevel = NULL; char *newlevel = NULL; char *service = NULL; char **deporder = NULL; @@ -780,6 +781,7 @@ int main (int argc, char **argv) rc_plugin_load (); /* Load current softlevel */ + bootlevel = getenv ("RC_BOOTLEVEL"); runlevel = rc_get_runlevel (); /* Check we're in the runlevel requested, ie from @@ -965,7 +967,7 @@ int main (int argc, char **argv) The only downside of this approach and ours is that we have to hard code the device node to the init script to simulate the coldplug into runlevel for our dependency tree to work. */ - if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0 && + if (newlevel && strcmp (newlevel, bootlevel) == 0 && (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && rc_is_env ("RC_COLDPLUG", "yes")) @@ -1015,7 +1017,7 @@ int main (int argc, char **argv) types = rc_strlist_add (types, "iuse"); types = rc_strlist_add (types, "iafter"); deporder = rc_get_depends (deptree, types, stop_services, - runlevel, depoptions); + runlevel, depoptions | RC_DEP_STOP); rc_strlist_free (stop_services); rc_strlist_free (types); stop_services = deporder; @@ -1029,7 +1031,7 @@ int main (int argc, char **argv) /* Load our start services now. We have different rules dependent on runlevel. */ - if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) { + if (newlevel && strcmp (newlevel, bootlevel) == 0) { if (coldplugged_services) { einfon ("Device initiated services:"); STRLIST_FOREACH (coldplugged_services, service, i) { @@ -1051,15 +1053,16 @@ int main (int argc, char **argv) strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) { /* We need to include the boot runlevel services if we're not in it */ - start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT, - RC_LS_INITD); + char **services = rc_services_in_runlevel (bootlevel); + + start_services = rc_strlist_join (start_services, services); + services = rc_services_in_runlevel (newlevel ? newlevel : runlevel); + start_services = rc_strlist_join (start_services, services); + services = NULL; + STRLIST_FOREACH (coldplugged_services, service, i) start_services = rc_strlist_add (start_services, service); - tmp = rc_strcatpaths (RC_RUNLEVELDIR, - newlevel ? newlevel : runlevel, (char *) NULL); - start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); - CHAR_FREE (tmp); } } @@ -1199,7 +1202,7 @@ int main (int argc, char **argv) types = rc_strlist_add (types, "iuse"); types = rc_strlist_add (types, "iafter"); deporder = rc_get_depends (deptree, types, start_services, - runlevel, depoptions); + runlevel, depoptions | RC_DEP_START); rc_strlist_free (types); types = NULL; rc_strlist_free (start_services); @@ -1248,7 +1251,7 @@ interactive_option: rc_plugin_run (rc_hook_runlevel_start_out, runlevel); /* Store our interactive status for boot */ - if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0) + if (interactive && strcmp (runlevel, bootlevel) == 0) mark_interactive (); else { if (rc_exists (INTERACTIVE)) diff --git a/src/runscript.c b/src/runscript.c index e817d0c8..876cddc7 100644 --- a/src/runscript.c +++ b/src/runscript.c @@ -573,9 +573,6 @@ static void svc_start (bool deps) rc_plugin_run (rc_hook_service_start_in, applet); hook_out = rc_hook_service_start_out; - if (rc_is_env ("RC_STRICT_DEPEND", "yes")) - depoptions |= RC_DEP_STRICT; - if (rc_is_env ("IN_HOTPLUG", "1") || in_background) { if (! rc_service_state (service, rc_service_inactive) && ! rc_service_state (service, rc_service_stopped)) @@ -598,6 +595,12 @@ static void svc_start (bool deps) make_exclusive (service); + if (rc_is_env ("RC_DEPEND_STRICT", "yes")) + depoptions |= RC_DEP_STRICT; + + if (rc_runlevel_starting ()) + depoptions |= RC_DEP_START; + if (deps) { if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) eerrorx ("failed to load deptree"); @@ -828,9 +831,12 @@ static void svc_stop (bool deps) char *svc; int i; - if (rc_is_env ("RC_STRICT_DEPEND", "yes")) + if (rc_is_env ("RC_DEPEND_STRICT", "yes")) depoptions |= RC_DEP_STRICT; + if (rc_runlevel_stopping ()) + depoptions |= RC_DEP_STOP; + if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) eerrorx ("failed to load deptree"); @@ -1180,6 +1186,11 @@ int main (int argc, char **argv) strcmp (optarg, "iafter") == 0 || strcmp (optarg, "ibefore") == 0 || strcmp (optarg, "iprovide") == 0) { + int depoptions = RC_DEP_TRACE; + + if (rc_is_env ("RC_DEPEND_STRICT", "yes")) + depoptions |= RC_DEP_STRICT; + if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) eerrorx ("failed to load deptree"); @@ -1188,7 +1199,8 @@ int main (int argc, char **argv) rc_strlist_free (svclist); svclist = rc_strlist_add (NULL, applet); rc_strlist_free (services); - services = rc_get_depends (deptree, types, svclist, softlevel, 0); + services = rc_get_depends (deptree, types, svclist, + softlevel, depoptions); STRLIST_FOREACH (services, svc, i) printf ("%s%s", i == 1 ? "" : " ", svc); printf ("\n"); |