|
Lines 182-188
valid_service(const char *runlevel, const char *service, const char *type)
|
Link Here
|
|---|
|
{ | { |
RC_SERVICE state; | RC_SERVICE state; |
| |
if (strcmp(type, "ineed") == 0 || |
if (!runlevel || |
|
strcmp(type, "ineed") == 0 || |
strcmp(type, "needsme") == 0) | strcmp(type, "needsme") == 0) |
return true; | return true; |
| |
|
Lines 251-257
get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
Link Here
|
|---|
|
provided dependancy can change depending on runlevel state. | provided dependancy can change depending on runlevel state. |
*/ | */ |
static RC_STRINGLIST * | static RC_STRINGLIST * |
get_provided (const RC_DEPINFO *depinfo, const char *runlevel, int options) |
get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options) |
{ | { |
RC_DEPTYPE *dt; | RC_DEPTYPE *dt; |
RC_STRINGLIST *providers = rc_stringlist_new(); | RC_STRINGLIST *providers = rc_stringlist_new(); |
|
Lines 682-723
rc_deptree_update_needed(void)
|
Link Here
|
|---|
|
} | } |
librc_hidden_def(rc_deptree_update_needed) | librc_hidden_def(rc_deptree_update_needed) |
| |
/* This is a 5 phase operation |
/* This is a 6 phase operation |
Phase 1 is a shell script which loads each init script and config in turn | Phase 1 is a shell script which loads each init script and config in turn |
and echos their dependency info to stdout | and echos their dependency info to stdout |
Phase 2 takes that and populates a depinfo object with that data | Phase 2 takes that and populates a depinfo object with that data |
Phase 3 adds any provided services to the depinfo object | 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 |
Phase 5 saves the depinfo object to disk |
Phase 5 removes broken before dependencies |
|
Phase 6 saves the depinfo object to disk |
*/ | */ |
bool | bool |
rc_deptree_update(void) | rc_deptree_update(void) |
{ | { |
FILE *fp; | FILE *fp; |
RC_DEPTREE *deptree; |
RC_DEPTREE *deptree, *providers; |
RC_DEPTREE *providers; |
RC_DEPINFO *depinfo = NULL, *depinfo_np, *di; |
RC_DEPINFO *depinfo = NULL; |
RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide; |
RC_DEPINFO *depinfo_np; |
RC_STRINGLIST *config, *types, *sorted, *visited; |
RC_DEPINFO *di; |
RC_STRING *s, *s2, *s2_np, *s3, *s4; |
RC_DEPTYPE *deptype = NULL; |
|
RC_DEPTYPE *dt; |
|
RC_DEPTYPE *dt_np; |
|
RC_STRINGLIST *config; |
|
RC_STRING *s; |
|
RC_STRING *s2; |
|
RC_DEPTYPE *provide; |
|
char *line = NULL; | char *line = NULL; |
size_t len = 0; | size_t len = 0; |
char *depend; |
char *depend, *depends, *service, *type, *nosys; |
char *depends; |
size_t i, k, l; |
char *service; |
bool retval = true; |
char *type; |
|
size_t i; |
|
size_t k; |
|
size_t l; |
|
int retval = true; |
|
const char *sys = rc_sys(); | const char *sys = rc_sys(); |
char *nosys; |
|
| |
/* Some init scripts need RC_LIBDIR to source stuff | /* Some init scripts need RC_LIBDIR to source stuff |
Ideally we should be setting our full env instead */ | Ideally we should be setting our full env instead */ |
|
Lines 876-882
rc_deptree_update(void)
|
Link Here
|
|---|
|
TAILQ_FOREACH(s, deptype->services, entries) { | TAILQ_FOREACH(s, deptype->services, entries) { |
di = get_depinfo(deptree, s->value); | di = get_depinfo(deptree, s->value); |
if (!di) { | if (!di) { |
if (strcmp (deptype->type, "ineed") == 0) |
if (strcmp(deptype->type, "ineed") == 0) |
fprintf (stderr, | fprintf (stderr, |
"Service `%s' needs non" | "Service `%s' needs non" |
" existant service `%s'\n", | " existant service `%s'\n", |
|
Lines 895-907
rc_deptree_update(void)
|
Link Here
|
|---|
|
} | } |
} | } |
| |
/* Phase 5 - save to disk |
|
|
/* Phase 5 - Remove broken before directives */ |
|
types = rc_stringlist_new(); |
|
rc_stringlist_add(types, "ineed"); |
|
rc_stringlist_add(types, "iuse"); |
|
rc_stringlist_add(types, "iafter"); |
|
STAILQ_FOREACH(depinfo, deptree, entries) { |
|
deptype = get_deptype(depinfo, "ibefore"); |
|
if (!deptype) |
|
continue; |
|
sorted = NULL; |
|
visited = rc_stringlist_new(); |
|
visit_service(deptree, types, &sorted, visited, depinfo, |
|
NULL, 0); |
|
rc_stringlist_free(visited); |
|
if (!sorted) |
|
continue; |
|
TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) { |
|
TAILQ_FOREACH(s3, sorted, entries) { |
|
di = get_depinfo(deptree, s3->value); |
|
if (!di) |
|
continue; |
|
if (strcmp(s2->value, s3->value) == 0) { |
|
dt = get_deptype(di, "iafter"); |
|
if (dt) |
|
rc_stringlist_delete(dt->services, depinfo->service); |
|
break; |
|
} |
|
dt = get_deptype(di, "iprovide"); |
|
if (!dt) |
|
continue; |
|
TAILQ_FOREACH(s4, dt->services, entries) { |
|
if (strcmp(s4->value, s2->value) == 0) |
|
break; |
|
} |
|
if (s4) { |
|
di = get_depinfo(deptree, s4->value); |
|
if (di) { |
|
dt = get_deptype(di, "iafter"); |
|
if (dt) |
|
rc_stringlist_delete(dt->services, depinfo->service); |
|
} |
|
break; |
|
} |
|
} |
|
if (s3) |
|
rc_stringlist_delete(deptype->services, s2->value); |
|
} |
|
rc_stringlist_free(sorted); |
|
} |
|
rc_stringlist_free(types); |
|
|
|
/* Phase 6 - save to disk |
Now that we're purely in C, do we need to keep a shell parseable file? | 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 | I think yes as then it stays human readable |
This works and should be entirely shell parseable provided that depend | This works and should be entirely shell parseable provided that depend |
names don't have any non shell variable characters in | names don't have any non shell variable characters in |
*/ | */ |
if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) { |
if ((fp = fopen(RC_DEPTREE_CACHE, "w"))) { |
i = 0; | i = 0; |
STAILQ_FOREACH(depinfo, deptree, entries) { | STAILQ_FOREACH(depinfo, deptree, entries) { |
fprintf(fp, "depinfo_%zu_service='%s'\n", | fprintf(fp, "depinfo_%zu_service='%s'\n", |
|
Lines 935-945
rc_deptree_update(void)
|
Link Here
|
|---|
|
RC_DEPCONFIG, strerror(errno)); | RC_DEPCONFIG, strerror(errno)); |
retval = false; | retval = false; |
} | } |
rc_stringlist_free (config); |
|
} else { | } else { |
unlink(RC_DEPCONFIG); | unlink(RC_DEPCONFIG); |
} | } |
| |
|
rc_stringlist_free(config); |
rc_deptree_free(deptree); | rc_deptree_free(deptree); |
return retval; | return retval; |
} | } |