diff options
Diffstat (limited to 'src/librc')
-rw-r--r-- | src/librc/librc-depend.c | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index cb38f190..4f72f2df 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -833,7 +833,7 @@ filter_sys(RC_DEPTREE *deptree, const char *sys) } static bool -deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config) +deptree_generate(const char *target, RC_DEPTREE *deptree, RC_STRINGLIST **config) { FILE *fp; RC_DEPTREE *providers; @@ -854,10 +854,21 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config) if (uname(&uts) == 0) setenv("RC_UNAME", uts.sysname, 1); /* Phase 1 - source all init scripts and print dependencies */ - if (!(fp = popen(GENDEP, "r"))) + + if (target) { + char *cmd; + xasprintf(&cmd, GENDEP " %s", target); + fp = popen(cmd, "r"); + free(cmd); + } else { + fp = popen(GENDEP, "r"); + } + + if (!fp) return false; - *config = rc_stringlist_new(); + if (config) + *config = rc_stringlist_new(); while ((size = getline(&line, &len, fp)) != -1) { line[size - 1] = '\0'; @@ -895,7 +906,8 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config) continue; if (strcmp(type, "config") == 0) { - rc_stringlist_addu(*config, depend); + if (config) + rc_stringlist_addu(*config, depend); continue; } @@ -928,9 +940,9 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config) } /* If we're after something, remove us from the before list */ if (strcmp(type, "iafter") == 0 || - strcmp(type, "ineed") == 0 || - strcmp(type, "iwant") == 0 || - strcmp(type, "iuse") == 0) { + strcmp(type, "ineed") == 0 || + strcmp(type, "iwant") == 0 || + strcmp(type, "iuse") == 0) { if ((dt = get_deptype(depinfo, "ibefore"))) rc_stringlist_delete(dt->services, depend); } @@ -964,15 +976,42 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config) return true; } +static RC_DEPINFO * +make_dylink_depinfo(RC_DEPTREE *deptree, const char *service) +{ + RC_DEPINFO *di = NULL; + char *target_file = NULL; + char *base = rc_service_base(service); + if (!base) + return NULL; + target_file = rc_service_dylink(base, service); + if (!target_file) + goto out; + /* TODO: integrate configuration checking for dynamic services */ + if (!deptree_generate(target_file, deptree, NULL)) + goto out; + + di = get_depinfo(deptree, service); + +out: + free(base); + free(target_file); + return di; +} + /* This is a 7 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 + and echos their dependency info to stdout and populates a depinfo object + with that data + Phase 2 filters services for system compatibility (i.e. keyword -container) Phase 3 adds any provided services to the depinfo object - Phase 4 scans that depinfo object and puts in backlinks + + Phase 4 scans that depinfo object and puts in backlinks, and dynamically + links services on the <base>.<service> format that are missing. Phase 5 removes broken before dependencies Phase 6 looks for duplicate services indicating a real and virtual service with the same names + Phase 7 saves the depinfo object to disk */ bool @@ -992,12 +1031,13 @@ rc_deptree_update(void) deptree = xmalloc(sizeof(*deptree)); TAILQ_INIT(deptree); - if (!deptree_generate(deptree, &config)) { + /* Phases 1..3 - generate intial deptree */ + if (!deptree_generate(NULL, deptree, &config)) { free(deptree); return false; } - /* Phase 4 - backreference our depends */ + /* Phase 4 - backreference our depends and dylink services */ TAILQ_FOREACH(depinfo, deptree, entries) { for (size_t i = 0; deppairs[i].depend; i++) { deptype = get_deptype(depinfo, deppairs[i].depend); @@ -1005,7 +1045,7 @@ rc_deptree_update(void) continue; TAILQ_FOREACH(s, deptype->services, entries) { di = get_depinfo(deptree, s->value); - if (!di) { + if (!di && !(di = make_dylink_depinfo(deptree, s->value))) { if (strcmp(deptype->type, "ineed") == 0) { fprintf(stderr, "Service '%s' needs non existent service '%s'\n", depinfo->service, s->value); |