aboutsummaryrefslogtreecommitdiff
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.c66
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);