aboutsummaryrefslogtreecommitdiff
path: root/initd/config.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-05-13 19:13:04 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2020-05-14 01:26:14 +0200
commitdbe89195b258c1101b5dd37dfbf5f0d71c25e0fa (patch)
tree6a4192ebe460b8a64f739209bc0269933304da9b /initd/config.c
parentf731537024c367368b728ed01c9232c3b1951589 (diff)
initd: split configuration handling into "config.c"
This commit splits off only the handling of the service configuration and handling of the run time state and adds an abstraction layer in the form of functions that have to be called to access the data. Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
Diffstat (limited to 'initd/config.c')
-rw-r--r--initd/config.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/initd/config.c b/initd/config.c
new file mode 100644
index 0000000..7f9f25c
--- /dev/null
+++ b/initd/config.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: ISC */
+#include "init.h"
+
+/* service configurations */
+static service_list_t cfg;
+
+/* service run time data, sorted by target and topological order */
+static svc_run_data_t *rt_data = NULL;
+static size_t rt_count = 0;
+
+/* maps a target to range in rt_data */
+static size_t queue_start[TGT_MAX];
+static size_t queue_count[TGT_MAX];
+
+/* current state */
+static size_t queue_idx = 0;
+static int target = TGT_BOOT;
+static size_t singleshot = 0;
+
+int config_load(void)
+{
+ service_t *it;
+ size_t i, j;
+
+ if (svcscan(SVCDIR, &cfg))
+ return -1;
+
+ /* allocate run time data */
+ rt_count = 0;
+
+ for (i = 0; i < TGT_MAX; ++i) {
+ for (it = cfg.targets[i]; it != NULL; it = it->next)
+ ++rt_count;
+ }
+
+ rt_data = calloc(rt_count, sizeof(rt_data[0]));
+ if (rt_data == NULL) {
+ rt_count = 0;
+ del_svc_list(&cfg);
+ return -1;
+ }
+
+ /* map runtime data to services */
+ j = 0;
+
+ for (i = 0; i < TGT_MAX; ++i) {
+ queue_start[i] = j;
+
+ for (it = cfg.targets[i]; it != NULL; it = it->next) {
+ rt_data[j].svc = it;
+ rt_data[j].state = STATE_OFF;
+ rt_data[j].pid = -1;
+ ++j;
+ }
+
+ queue_count[i] = j - queue_start[i];
+ }
+
+ /* initialize state */
+ for (i = 0; i < queue_count[target]; ++i)
+ rt_data[queue_start[target] + i].state = STATE_QUEUED;
+
+ return 0;
+}
+
+svc_run_data_t *config_rt_data_by_pid(pid_t pid)
+{
+ size_t i;
+
+ if (pid <= 1)
+ return NULL;
+
+ for (i = 0; i < rt_count; ++i) {
+ if (rt_data[i].pid == pid)
+ return rt_data + i;
+ }
+
+ return NULL;
+}
+
+svc_run_data_t *config_dequeue(void)
+{
+ if (queue_idx >= queue_count[target])
+ return NULL;
+
+ return rt_data + queue_start[target] + queue_idx++;
+}
+
+void config_set_target(int tgt)
+{
+ if (target == TGT_REBOOT || target == TGT_SHUTDOWN || target == tgt)
+ return;
+
+ /* TODO:
+ - if there are services left in the queue of the current target:
+ - refuse unless the new target is shutdown/reboot?
+ - mark pending as "STATE_OFF"
+ - if the new target is reboot/shutdown
+ - enqueue the currently running services as "stop those"?
+ */
+
+ target = tgt;
+ queue_idx = 0;
+}
+
+int config_get_current_target(void)
+{
+ return target;
+}
+
+bool config_is_current_target_complete(void)
+{
+ return singleshot == 0 && queue_idx >= queue_count[target];
+}
+
+bool config_should_respawn(void)
+{
+ return target != TGT_REBOOT && target != TGT_SHUTDOWN;
+}
+
+void config_singleshot_started(void)
+{
+ singleshot++;
+}
+
+void config_singleshot_terminated(void)
+{
+ assert(singleshot > 0);
+
+ singleshot--;
+}