aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-07-19 11:42:53 +0200
committerAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-07-20 03:19:47 +0200
commiteb4eac88ebbbae5bf4bc3457b465ed537e6fe917 (patch)
tree00a53708eca2b01043c4db8b6e1b7dc832c375f3
parent5caae0d24db8c739d3b659ec1b6a0e9e6641a571 (diff)
librc-depend.c: split update function into subfunctions
in preparation for dynamic service discovery, modularize the dependency tree generation and update into distinct functions. also helps with readability. Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
-rw-r--r--src/librc/librc-depend.c162
1 files changed, 89 insertions, 73 deletions
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
index 9f592cfe..cb38f190 100644
--- a/src/librc/librc-depend.c
+++ b/src/librc/librc-depend.c
@@ -792,38 +792,59 @@ rc_deptree_update_needed(time_t *newest, char *file)
return newer;
}
-/* 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
- Phase 3 adds any provided services to the depinfo object
- Phase 4 scans that depinfo object and puts in backlinks
- 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
-rc_deptree_update(void)
+static inline bool
+is_nosys(const char *keyword, const char *sys)
+{
+ return (strncmp(keyword, "no", 2) == 0 && strcasecmp(keyword + 2, sys) == 0)
+ || (strncmp(keyword, "-", 1) == 0 && strcasecmp(keyword + 1, sys) == 0);
+}
+
+static void
+filter_sys(RC_DEPTREE *deptree, const char *sys)
{
+ RC_DEPINFO *depinfo, *depinfo_save, *di;
+ RC_DEPTYPE *deptype, *provide, *dt, *dt_save;
+ RC_STRING *s, *s2;
+ TAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_save) {
+ if (!(deptype = get_deptype(depinfo, "keyword")))
+ continue;
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ if (!is_nosys(s->value, sys))
+ continue;
+ provide = get_deptype(depinfo, "iprovide");
+ TAILQ_REMOVE(deptree, depinfo, entries);
+ TAILQ_FOREACH(di, deptree, entries) {
+ TAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_save) {
+ rc_stringlist_delete(dt->services, depinfo->service);
+ if (provide)
+ TAILQ_FOREACH(s2, provide->services, entries)
+ rc_stringlist_delete(dt->services, s2->value);
+ if (!TAILQ_FIRST(dt->services)) {
+ TAILQ_REMOVE(&di->depends, dt, entries);
+ free(dt->type);
+ free(dt->services);
+ free(dt);
+ }
+ }
+ }
+ }
+ }
+}
+
+static bool
+deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
+{
FILE *fp;
- RC_DEPTREE *deptree, *providers;
- RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
- RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
- RC_STRINGLIST *config, *dupes, *types, *sorted, *visited;
- RC_STRING *s, *s2, *s2_np, *s3, *s4;
+ RC_DEPTREE *providers;
+ RC_DEPINFO *depinfo = NULL;
+ RC_DEPTYPE *deptype = NULL, *dt;
char *line = NULL;
size_t len = 0;
ssize_t size;
char *depend, *depends, *service, *type;
- char *deptree_cache;
- char *depconfig;
- size_t i, l;
- bool retval = true;
const char *sys = rc_sys();
struct utsname uts;
- int serrno;
/* Some init scripts need RC_LIBEXECDIR to source stuff
Ideally we should be setting our full env instead */
@@ -836,10 +857,8 @@ rc_deptree_update(void)
if (!(fp = popen(GENDEP, "r")))
return false;
- config = rc_stringlist_new();
+ *config = rc_stringlist_new();
- deptree = xmalloc(sizeof(*deptree));
- TAILQ_INIT(deptree);
while ((size = getline(&line, &len, fp)) != -1) {
line[size - 1] = '\0';
depends = line;
@@ -871,11 +890,12 @@ rc_deptree_update(void)
/* Now add each depend to our type.
We do this individually so we handle multiple spaces gracefully */
while ((depend = strsep(&depends, " "))) {
+ size_t l;
if (depend[0] == 0)
continue;
if (strcmp(type, "config") == 0) {
- rc_stringlist_addu(config, depend);
+ rc_stringlist_addu(*config, depend);
continue;
}
@@ -921,55 +941,15 @@ rc_deptree_update(void)
/* Phase 2 - if we're a special system, remove services that don't
* work for them. This doesn't stop them from being run directly. */
- if (sys) {
- char *nosys, *onosys;
-
- len = strlen(sys);
- nosys = xmalloc(len + 2);
- nosys[0] = '-';
- for (i = 0; i < len; i++)
- nosys[i + 1] = (char)tolower((unsigned char)sys[i]);
- nosys[i + 1] = '\0';
-
- onosys = xmalloc(len + 3);
- onosys[0] = 'n';
- onosys[1] = 'o';
- for (i = 0; i < len; i++)
- onosys[i + 2] = (char)tolower((unsigned char)sys[i]);
- onosys[i + 2] = '\0';
-
- TAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np) {
- if (!(deptype = get_deptype(depinfo, "keyword")))
- continue;
- TAILQ_FOREACH(s, deptype->services, entries) {
- if (strcmp(s->value, nosys) != 0 && strcmp(s->value, onosys) != 0)
- continue;
- provide = get_deptype(depinfo, "iprovide");
- TAILQ_REMOVE(deptree, depinfo, entries);
- TAILQ_FOREACH(di, deptree, entries) {
- TAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
- rc_stringlist_delete(dt->services, depinfo->service);
- if (provide)
- TAILQ_FOREACH(s2, provide->services, entries)
- rc_stringlist_delete(dt->services, s2->value);
- if (!TAILQ_FIRST(dt->services)) {
- TAILQ_REMOVE(&di->depends, dt, entries);
- free(dt->type);
- free(dt->services);
- free(dt);
- }
- }
- }
- }
- }
- free(nosys);
- free(onosys);
- }
+ if (sys)
+ filter_sys(deptree, sys);
/* Phase 3 - add our providers to the tree */
providers = xmalloc(sizeof(*providers));
TAILQ_INIT(providers);
TAILQ_FOREACH(depinfo, deptree, entries) {
+ RC_DEPINFO *di;
+ RC_STRING *s;
if (!(deptype = get_deptype(depinfo, "iprovide")))
continue;
TAILQ_FOREACH(s, deptype->services, entries) {
@@ -981,9 +961,45 @@ rc_deptree_update(void)
TAILQ_CONCAT(deptree, providers, entries);
free(providers);
+ return true;
+}
+
+/* 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
+ Phase 3 adds any provided services to the depinfo object
+ Phase 4 scans that depinfo object and puts in backlinks
+ 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
+rc_deptree_update(void)
+{
+
+ FILE *fp;
+ RC_DEPTREE *deptree;
+ RC_DEPINFO *depinfo = NULL, *di;
+ RC_DEPTYPE *deptype = NULL, *dt;
+ RC_STRINGLIST *config, *dupes, *types, *sorted, *visited;
+ RC_STRING *s, *s2, *s2_np, *s3, *s4;
+ char *deptree_cache;
+ char *depconfig;
+ bool retval = true;
+ int serrno;
+
+ deptree = xmalloc(sizeof(*deptree));
+ TAILQ_INIT(deptree);
+ if (!deptree_generate(deptree, &config)) {
+ free(deptree);
+ return false;
+ }
+
/* Phase 4 - backreference our depends */
TAILQ_FOREACH(depinfo, deptree, entries) {
- for (i = 0; deppairs[i].depend; i++) {
+ for (size_t i = 0; deppairs[i].depend; i++) {
deptype = get_deptype(depinfo, deppairs[i].depend);
if (!deptype)
continue;
@@ -1082,7 +1098,7 @@ rc_deptree_update(void)
*/
xasprintf(&deptree_cache, "%s/%s", rc_service_dir(), RC_DEPTREE_CACHE);
if ((fp = fopen(deptree_cache, "w"))) {
- i = 0;
+ size_t i = 0;
TAILQ_FOREACH(depinfo, deptree, entries) {
fprintf(fp, "depinfo_%zu_service='%s'\n", i, depinfo->service);
TAILQ_FOREACH(deptype, &depinfo->depends, entries) {