From e7653b20477d7aa587d40e72b7982356df9f8a91 Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Mon, 30 Oct 2023 21:01:02 +1100
Subject: [PATCH] add servicedir entry at live addon. Add enabled at
 configuration group entry. Move status entry from path to live addon

---
 src/include/66/service.h                      |  16 +-
 src/lib66/exec/ssexec_init.c                  |  20 +-
 src/lib66/exec/ssexec_resolve.c               | 176 +++++++++---------
 src/lib66/exec/ssexec_restart.c               |   2 +-
 src/lib66/exec/ssexec_status.c                |   4 +-
 src/lib66/exec/ssexec_tree_signal.c           |   2 +-
 src/lib66/info/info_graph_display_service.c   |   4 +-
 src/lib66/service/service_enable_disable.c    |  27 ++-
 src/lib66/service/service_graph_collect.c     |   2 +-
 src/lib66/service/service_resolve_copy.c      |   4 +-
 .../service/service_resolve_get_field_tosa.c  |  17 +-
 .../service/service_resolve_modify_field.c    |  21 ++-
 src/lib66/service/service_resolve_read_cdb.c  |  10 +-
 src/lib66/service/service_resolve_write_cdb.c |   6 +-
 src/lib66/state/state_check.c                 |   2 +-
 src/lib66/state/state_read.c                  |   2 +-
 src/lib66/state/state_rmfile.c                |   2 +-
 src/lib66/state/state_write.c                 |  16 +-
 18 files changed, 194 insertions(+), 139 deletions(-)

diff --git a/src/include/66/service.h b/src/include/66/service.h
index fd21f449..1b2dbbe0 100644
--- a/src/include/66/service.h
+++ b/src/include/66/service.h
@@ -32,11 +32,10 @@ struct resolve_service_addon_path_s
 {
     uint32_t home ; // string, /var/lib/66 or /home/user/.66
     uint32_t frontend ;  // string, /home/<user>/.66/service or /etc/66/service or /usr/lib/66/service
-    uint32_t status ; //string, /var/lib/66/system/service/svc/service_name/state/status
-    uint32_t servicedir ; //string, /var/lib/66/system/service/svc/service_name or for module /var/lib/66/system/service/svc/module_name/svc/service_name
+    uint32_t servicedir ; //string, /var/lib/66/system/service/svc/service_name
 } ;
 
-#define RESOLVE_SERVICE_ADDON_PATH_ZERO { 0,0,0,0 }
+#define RESOLVE_SERVICE_ADDON_PATH_ZERO { 0,0,0 }
 
 typedef struct resolve_service_addon_dependencies_s resolve_service_addon_dependencies_t, *resolve_service_addon_dependencies_t_ref ;
 struct resolve_service_addon_dependencies_s
@@ -99,6 +98,8 @@ typedef struct resolve_service_addon_live_s resolve_service_addon_live_t, *resol
 struct resolve_service_addon_live_s
 {
     uint32_t livedir ; // string, /run/66
+    uint32_t status ; //string, /var/lib/66/system/.resolve/service/service_name/state/status
+    uint32_t servicedir ; // string, /run/66/state/uid/service_name
     uint32_t scandir ; // string, /run/66/state/uid/service_name/scandir/service_name -> /var/lib/66/system/service/svc/service_name -> /run/66/scandir/uid
     uint32_t statedir ; // string, /run/66/state/uid/service_name/state -> /var/lib/66/system/service/svc/service_name/state
     uint32_t eventdir ; // string, /run/66/state/uid/service_name/event -> /var/lib/66/system/service/svc/service_name/event
@@ -108,7 +109,7 @@ struct resolve_service_addon_live_s
     uint32_t oneshotddir ; // string, /run/66/state/uid/service_name/scandir/oneshotd
 } ;
 
-#define RESOLVE_SERVICE_ADDON_LIVE_ZERO { 0,0,0,0,0,0,0,0 }
+#define RESOLVE_SERVICE_ADDON_LIVE_ZERO { 0,0,0,0,0,0,0,0,0,0 }
 
 typedef struct resolve_service_addon_logger_s resolve_service_addon_logger_t, *resolve_service_addon_logger_t_ref ;
 struct resolve_service_addon_logger_s
@@ -182,6 +183,7 @@ struct resolve_service_s
     uint32_t treename ; // string
     uint32_t user ; // string
     uint32_t inmodule ; // string, name of the module which depend on
+    uint32_t enabled ; // integer, 0 not enabled
 
     resolve_service_addon_path_t path ;
     resolve_service_addon_dependencies_t dependencies ;
@@ -194,7 +196,7 @@ struct resolve_service_s
 } ;
 
 #define RESOLVE_SERVICE_ZERO { 0,STRALLOC_ZERO, \
-                               0,0,0,0,0,5,0,0,0,0,0,0,0,0, \
+                               0,0,0,0,0,5,0,0,0,0,0,0,0,0,0, \
                                RESOLVE_SERVICE_ADDON_PATH_ZERO, \
                                RESOLVE_SERVICE_ADDON_DEPENDENCIES_ZERO, \
                                RESOLVE_SERVICE_ADDON_EXECUTE_ZERO, \
@@ -222,11 +224,11 @@ enum resolve_service_enum_e
     E_RESOLVE_SERVICE_TREENAME,
     E_RESOLVE_SERVICE_USER,
     E_RESOLVE_SERVICE_INMODULE,
+    E_RESOLVE_SERVICE_ENABLED,
 
     // path
     E_RESOLVE_SERVICE_HOME,
     E_RESOLVE_SERVICE_FRONTEND,
-    E_RESOLVE_SERVICE_STATUS,
     E_RESOLVE_SERVICE_SERVICEDIR,
 
     // dependencies
@@ -259,6 +261,8 @@ enum resolve_service_enum_e
 
     // live
     E_RESOLVE_SERVICE_LIVEDIR,
+    E_RESOLVE_SERVICE_STATUS,
+    E_RESOLVE_SERVICE_SERVICEDIR_LIVE,
     E_RESOLVE_SERVICE_SCANDIR,
     E_RESOLVE_SERVICE_STATEDIR,
     E_RESOLVE_SERVICE_EVENTDIR,
diff --git a/src/lib66/exec/ssexec_init.c b/src/lib66/exec/ssexec_init.c
index 32bada61..ec84853d 100644
--- a/src/lib66/exec/ssexec_init.c
+++ b/src/lib66/exec/ssexec_init.c
@@ -33,16 +33,20 @@
 #include <66/state.h>
 #include <66/graph.h>
 #include <66/sanitize.h>
+#include <66/utils.h>
 
 static void doit(stralloc *sa, ssexec_t *info, uint8_t earlier)
 {
+    log_flow() ;
+
     uint32_t flag = 0 ;
     graph_t graph = GRAPH_ZERO ;
-    ss_state_t ste = STATE_ZERO ;
 
     unsigned int areslen = 0, list[SS_MAX_SERVICE + 1], visit[SS_MAX_SERVICE + 1], nservice = 0, n = 0 ;
     resolve_service_t ares[SS_MAX_SERVICE + 1] ;
 
+    memset(&visit, 0, SS_MAX_SERVICE + 1 * sizeof(unsigned int)) ;
+
     FLAGS_SET(flag, STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_WANTUP) ;
 
     if (earlier)
@@ -82,12 +86,15 @@ static void doit(stralloc *sa, ssexec_t *info, uint8_t earlier)
 
             } else {
 
-                if (!state_read(&ste, &ares[aresid]))
-                    log_dieusys(LOG_EXIT_SYS, "read state file of service: ", sa->s + n) ;
+                if (ares[aresid].enabled) {
 
-                if (service_is(&ste, STATE_FLAGS_ISENABLED) == STATE_FLAGS_TRUE) {
                     list[nservice++] = idx ;
                     visit[idx] = 1 ;
+
+                } else {
+
+                    log_trace("ignoring not enabled service: ", ares[aresid].sa.s + ares[aresid].name) ;
+
                 }
             }
 
@@ -117,12 +124,11 @@ static void doit(stralloc *sa, ssexec_t *info, uint8_t earlier)
 
                 } else {
 
-                    if (!state_read(&ste, &ares[aresid]))
-                        log_dieusys(LOG_EXIT_SYS, "read state file of service: ", name) ;
+                    if (ares[aresid].enabled) {
 
-                    if (service_is(&ste, STATE_FLAGS_ISENABLED) == STATE_FLAGS_TRUE) {
                         list[nservice++] = l[pos] ;
                         visit[l[pos]] = 1 ;
+
                     }
                 }
             }
diff --git a/src/lib66/exec/ssexec_resolve.c b/src/lib66/exec/ssexec_resolve.c
index 7bae3840..7d5905c4 100644
--- a/src/lib66/exec/ssexec_resolve.c
+++ b/src/lib66/exec/ssexec_resolve.c
@@ -14,6 +14,7 @@
 
 #include <string.h>
 #include <wchar.h>
+#include <stdint.h>
 
 #include <oblibs/log.h>
 #include <oblibs/sastr.h>
@@ -35,7 +36,7 @@
 #include <66/config.h>
 #include <66/state.h>
 
-#define MAXOPTS 72
+#define MAXOPTS 73
 
 static wchar_t const field_suffix[] = L" :" ;
 static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ;
@@ -77,85 +78,87 @@ static void info_display_int(char const *field, uint32_t element)
 
 static void info_display_service_field(resolve_service_t *res)
 {
-    info_display_string(fields[0], res->sa.s, res->name, 0) ;
-    info_display_string(fields[1], res->sa.s, res->description, 1) ;
-    info_display_string(fields[2], res->sa.s, res->version, 1) ;
-    info_display_int(fields[3], res->type) ;
-    info_display_int(fields[4], res->notify) ;
-    info_display_int(fields[5], res->maxdeath) ;
-    info_display_int(fields[6], res->earlier) ;
-    info_display_string(fields[7], res->sa.s, res->hiercopy, 1) ;
-    info_display_string(fields[8], res->sa.s, res->intree, 1) ;
-    info_display_string(fields[9], res->sa.s, res->ownerstr, 1) ;
-    info_display_int(fields[10], res->owner) ;
-    info_display_string(fields[11], res->sa.s, res->treename, 1) ;
-    info_display_string(fields[12], res->sa.s, res->user, 1) ;
-    info_display_string(fields[13], res->sa.s, res->inmodule, 1) ;
-
-    info_display_string(fields[14], res->sa.s, res->path.home, 1) ;
-    info_display_string(fields[15], res->sa.s, res->path.frontend, 1) ;
-    info_display_string(fields[16], res->sa.s, res->path.status, 1) ;
-    info_display_string(fields[17], res->sa.s, res->path.servicedir, 1) ;
-
-    info_display_string(fields[18], res->sa.s, res->dependencies.depends, 1) ;
-    info_display_string(fields[19], res->sa.s, res->dependencies.requiredby, 1) ;
-    info_display_string(fields[20], res->sa.s, res->dependencies.optsdeps, 1) ;
-    info_display_string(fields[21], res->sa.s, res->dependencies.contents, 1) ;
-    info_display_int(fields[22], res->dependencies.ndepends) ;
-    info_display_int(fields[23], res->dependencies.nrequiredby) ;
-    info_display_int(fields[24], res->dependencies.noptsdeps) ;
-    info_display_int(fields[25], res->dependencies.ncontents) ;
-
-    info_display_string(fields[26], res->sa.s, res->execute.run.run, 1) ;
-    info_display_string(fields[27], res->sa.s, res->execute.run.run_user, 1) ;
-    info_display_string(fields[28], res->sa.s, res->execute.run.build, 1) ;
-    info_display_string(fields[29], res->sa.s, res->execute.run.shebang, 1) ;
-    info_display_string(fields[30], res->sa.s, res->execute.run.runas, 1) ;
-    info_display_string(fields[31], res->sa.s, res->execute.finish.run, 1) ;
-    info_display_string(fields[32], res->sa.s, res->execute.finish.run_user, 1) ;
-    info_display_string(fields[33], res->sa.s, res->execute.finish.build, 1) ;
-    info_display_string(fields[34], res->sa.s, res->execute.finish.shebang, 1) ;
-    info_display_string(fields[35], res->sa.s, res->execute.finish.runas, 1) ;
-    info_display_int(fields[36], res->execute.timeout.kill) ;
-    info_display_int(fields[37], res->execute.timeout.finish) ;
-    info_display_int(fields[38], res->execute.timeout.up) ;
-    info_display_int(fields[39], res->execute.timeout.down) ;
-    info_display_int(fields[40], res->execute.down) ;
-    info_display_int(fields[41], res->execute.downsignal) ;
-
-    info_display_string(fields[42], res->sa.s, res->live.livedir, 1) ;
-    info_display_string(fields[43], res->sa.s, res->live.scandir, 1) ;
-    info_display_string(fields[44], res->sa.s, res->live.statedir, 1) ;
-    info_display_string(fields[45], res->sa.s, res->live.eventdir, 1) ;
-    info_display_string(fields[46], res->sa.s, res->live.notifdir, 1) ;
-    info_display_string(fields[47], res->sa.s, res->live.supervisedir, 1) ;
-    info_display_string(fields[48], res->sa.s, res->live.fdholderdir, 1) ;
-    info_display_string(fields[49], res->sa.s, res->live.oneshotddir, 1) ;
-
-    info_display_string(fields[50], res->sa.s, res->logger.name, 1) ;
-    info_display_string(fields[51], res->sa.s, res->logger.destination, 1) ;
-    info_display_int(fields[52], res->logger.backup) ;
-    info_display_int(fields[53], res->logger.maxsize) ;
-    info_display_int(fields[54], res->logger.timestamp) ;
-    info_display_string(fields[55], res->sa.s, res->logger.execute.run.run, 1) ;
-    info_display_string(fields[56], res->sa.s, res->logger.execute.run.run_user, 1) ;
-    info_display_string(fields[57], res->sa.s, res->logger.execute.run.build, 1) ;
-    info_display_string(fields[58], res->sa.s, res->logger.execute.run.shebang, 1) ;
-    info_display_string(fields[59], res->sa.s, res->logger.execute.run.runas, 1) ;
-    info_display_int(fields[60], res->logger.execute.timeout.kill) ;
-    info_display_int(fields[61], res->logger.execute.timeout.finish) ;
-
-    info_display_string(fields[62], res->sa.s, res->environ.env, 1) ;
-    info_display_string(fields[63], res->sa.s, res->environ.envdir, 1) ;
-    info_display_int(fields[64], res->environ.env_overwrite) ;
-
-    info_display_string(fields[65], res->sa.s, res->regex.configure, 1) ;
-    info_display_string(fields[66], res->sa.s, res->regex.directories, 1) ;
-    info_display_string(fields[67], res->sa.s, res->regex.files, 1) ;
-    info_display_string(fields[68], res->sa.s, res->regex.infiles, 1) ;
-    info_display_int(fields[69], res->regex.ndirectories) ;
-    info_display_int(fields[70], res->regex.nfiles) ;
-    info_display_int(fields[71], res->regex.ninfiles) ;
+    uint8_t m = 0 ;
+    info_display_string(fields[m++], res->sa.s, res->name, 0) ;
+    info_display_string(fields[m++], res->sa.s, res->description, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->version, 1) ;
+    info_display_int(fields[m++], res->type) ;
+    info_display_int(fields[m++], res->notify) ;
+    info_display_int(fields[m++], res->maxdeath) ;
+    info_display_int(fields[m++], res->earlier) ;
+    info_display_string(fields[m++], res->sa.s, res->hiercopy, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->intree, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->ownerstr, 1) ;
+    info_display_int(fields[m++], res->owner) ;
+    info_display_string(fields[m++], res->sa.s, res->treename, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->user, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->inmodule, 1) ;
+
+    info_display_string(fields[m++], res->sa.s, res->path.home, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->path.frontend, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->path.servicedir, 1) ;
+
+    info_display_string(fields[m++], res->sa.s, res->dependencies.depends, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->dependencies.requiredby, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->dependencies.optsdeps, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->dependencies.contents, 1) ;
+    info_display_int(fields[m++], res->dependencies.ndepends) ;
+    info_display_int(fields[m++], res->dependencies.nrequiredby) ;
+    info_display_int(fields[m++], res->dependencies.noptsdeps) ;
+    info_display_int(fields[m++], res->dependencies.ncontents) ;
+
+    info_display_string(fields[m++], res->sa.s, res->execute.run.run, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.run.run_user, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.run.build, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.run.shebang, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.run.runas, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.finish.run, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.finish.run_user, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.finish.build, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.finish.shebang, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->execute.finish.runas, 1) ;
+    info_display_int(fields[m++], res->execute.timeout.kill) ;
+    info_display_int(fields[m++], res->execute.timeout.finish) ;
+    info_display_int(fields[m++], res->execute.timeout.up) ;
+    info_display_int(fields[m++], res->execute.timeout.down) ;
+    info_display_int(fields[m++], res->execute.down) ;
+    info_display_int(fields[m++], res->execute.downsignal) ;
+
+    info_display_string(fields[m++], res->sa.s, res->live.livedir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.status, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.servicedir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.scandir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.statedir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.eventdir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.notifdir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.supervisedir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.fdholderdir, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->live.oneshotddir, 1) ;
+
+    info_display_string(fields[m++], res->sa.s, res->logger.name, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.destination, 1) ;
+    info_display_int(fields[m++], res->logger.backup) ;
+    info_display_int(fields[m++], res->logger.maxsize) ;
+    info_display_int(fields[m++], res->logger.timestamp) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.execute.run.run, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.execute.run.run_user, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.execute.run.build, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.execute.run.shebang, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->logger.execute.run.runas, 1) ;
+    info_display_int(fields[m++], res->logger.execute.timeout.kill) ;
+    info_display_int(fields[m++], res->logger.execute.timeout.finish) ;
+
+    info_display_string(fields[m++], res->sa.s, res->environ.env, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->environ.envdir, 1) ;
+    info_display_int(fields[m++], res->environ.env_overwrite) ;
+
+    info_display_string(fields[m++], res->sa.s, res->regex.configure, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->regex.directories, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->regex.files, 1) ;
+    info_display_string(fields[m++], res->sa.s, res->regex.infiles, 1) ;
+    info_display_int(fields[m++], res->regex.ndirectories) ;
+    info_display_int(fields[m++], res->regex.nfiles) ;
+    info_display_int(fields[m], res->regex.ninfiles) ;
 
 }
 
@@ -186,8 +189,7 @@ int ssexec_resolve(int argc, char const *const *argv, ssexec_t *info)
 
         "home",
         "frontend",
-        "status", //17
-        "servicedir",
+        "servicedir", //17
 
         "depends",
         "requiredby",
@@ -216,13 +218,15 @@ int ssexec_resolve(int argc, char const *const *argv, ssexec_t *info)
         "downsignal", // 41
 
         "livedir",
+        "status",
+        "servicedir",
         "scandir",
         "statedir",
         "eventdir",
         "notifdir",
         "supervisedir",
         "fdholderdir",
-        "oneshotddir", //49
+        "oneshotddir", //50
 
         "logname" ,
         "logdestination" ,
@@ -235,11 +239,11 @@ int ssexec_resolve(int argc, char const *const *argv, ssexec_t *info)
         "logrun_shebang" ,
         "logrun_runas" ,
         "logtimeoutkill",
-        "logtimeoutfinish", // 61
+        "logtimeoutfinish", // 62
 
         "env",
         "envdir",
-        "env_overwrite", // 64
+        "env_overwrite", // 65
 
         "configure",
         "directories",
@@ -247,7 +251,7 @@ int ssexec_resolve(int argc, char const *const *argv, ssexec_t *info)
         "infiles",
         "ndirectories",
         "nfiles",
-        "ninfiles" // 71
+        "ninfiles" // 72
 
     } ;
 
diff --git a/src/lib66/exec/ssexec_restart.c b/src/lib66/exec/ssexec_restart.c
index 742f6586..da0a30c5 100644
--- a/src/lib66/exec/ssexec_restart.c
+++ b/src/lib66/exec/ssexec_restart.c
@@ -95,7 +95,7 @@ int ssexec_restart(int argc, char const *const *argv, ssexec_t *info)
         if (!state_read(&sta, &ares[aresid]))
             log_dieu(LOG_EXIT_SYS, "read state file of: ", argv[n]) ;
 
-        if (service_is(&sta, STATE_FLAGS_ISSUPERVISED) == STATE_FLAGS_FALSE)
+        if (sta.issupervised == STATE_FLAGS_FALSE)
             /** nothing to do */
             log_warn_return(LOG_EXIT_ZERO, "service: ", argv[n], " is not supervised -- try to start it first using '66 start ", argv[n], "'") ;
     }
diff --git a/src/lib66/exec/ssexec_status.c b/src/lib66/exec/ssexec_status.c
index 7e53a5c9..0b5da3b9 100644
--- a/src/lib66/exec/ssexec_status.c
+++ b/src/lib66/exec/ssexec_status.c
@@ -253,9 +253,9 @@ static void info_display_status(char const *field,resolve_service_t *res)
     if (!state_read(&ste, res))
         log_dieusys(LOG_EXIT_SYS, "read state file of: ", res->sa.s + res->name) ;
 
-    disen = service_is(&ste, STATE_FLAGS_ISENABLED) ;
+    disen = res->enabled ;
 
-    if (!bprintf(buffer_1,"%s%s%s%s", disen == STATE_FLAGS_TRUE ? log_color->valid : log_color->warning, disen == STATE_FLAGS_TRUE ? "enabled" : "disabled", log_color->off, ", "))
+    if (!bprintf(buffer_1,"%s%s%s%s", disen ? log_color->valid : log_color->warning, disen ? "enabled" : "disabled", log_color->off, ", "))
         log_dieusys(LOG_EXIT_SYS,"write to stdout") ;
 
     if (buffer_putsflush(buffer_1,"") == -1)
diff --git a/src/lib66/exec/ssexec_tree_signal.c b/src/lib66/exec/ssexec_tree_signal.c
index 056dee0e..447ba777 100644
--- a/src/lib66/exec/ssexec_tree_signal.c
+++ b/src/lib66/exec/ssexec_tree_signal.c
@@ -466,7 +466,7 @@ static int ssexec_callback(stralloc *sa, ssexec_t *info, unsigned int what)
         if (!state_read(&ste, &res))
             log_dieu(LOG_EXIT_SYS, "read state file of: ", name, " -- please make a bug report") ;
 
-        if (!what ? ste.isenabled : ste.issupervised == STATE_FLAGS_TRUE && ste.isearlier == STATE_FLAGS_FALSE) {
+        if (!what ? res.enabled : ste.issupervised == STATE_FLAGS_TRUE && !res.earlier) {
 
             if (get_rstrlen_until(name, SS_LOG_SUFFIX) < 0 && !res.inmodule)
                 if (!sastr_add_string(sa, name))
diff --git a/src/lib66/info/info_graph_display_service.c b/src/lib66/info/info_graph_display_service.c
index e7bc8881..01f1ac15 100644
--- a/src/lib66/info/info_graph_display_service.c
+++ b/src/lib66/info/info_graph_display_service.c
@@ -99,11 +99,11 @@ int info_graph_display_service(char const *name)
         "=", \
         ppid, \
 
-        service_is(&sta, STATE_FLAGS_ISENABLED) == STATE_FLAGS_TRUE ? log_color->valid : log_color->warning, \
+        res.enabled ? log_color->valid : log_color->warning, \
         "state", \
         log_color->off, \
         "=", \
-        service_is(&sta, STATE_FLAGS_ISENABLED) == STATE_FLAGS_TRUE ? "Enabled" : "Disabled", \
+        res.enabled ? "Enabled" : "Disabled", \
 
         log_color->blue, \
         "type",
diff --git a/src/lib66/service/service_enable_disable.c b/src/lib66/service/service_enable_disable.c
index 822a796f..6e4db159 100644
--- a/src/lib66/service/service_enable_disable.c
+++ b/src/lib66/service/service_enable_disable.c
@@ -63,9 +63,13 @@ void service_enable_disable(graph_t *g, unsigned int idx, resolve_service_t *are
     if (visit[idx] == VISIT_WHITE) {
 
         resolve_service_t_ref res = &ares[idx] ;
+        resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ;
 
-        if (!state_messenger(res, STATE_FLAGS_ISENABLED, !action ? STATE_FLAGS_FALSE : STATE_FLAGS_TRUE))
-            log_dieusys(LOG_EXIT_SYS, "send message to state of: ", res->sa.s + res->name) ;
+        if (!service_resolve_modify_field(res, E_RESOLVE_SERVICE_ENABLED, !action ? "0" : "1"))
+            log_dieu(LOG_EXIT_SYS, "modify resolve file of: ", res->sa.s + res->name) ;
+
+        if (!resolve_write_g(wres, res->sa.s + res->path.home, res->sa.s + res->name))
+            log_dieu(LOG_EXIT_SYS, "write  resolve file of: ", res->sa.s + res->name) ;
 
         if (propagate)
             service_enable_disable_deps(g, idx, ares, areslen, action, visit, propagate) ;
@@ -82,8 +86,13 @@ void service_enable_disable(graph_t *g, unsigned int idx, resolve_service_t *are
 
             if (visit[aresid] == VISIT_WHITE) {
 
-                if (!state_messenger(&ares[aresid], STATE_FLAGS_ISENABLED, !action ? STATE_FLAGS_FALSE : STATE_FLAGS_TRUE))
-                    log_dieusys(LOG_EXIT_SYS, "send message to state of: ", name) ;
+                wres = resolve_set_struct(DATA_SERVICE, &ares[aresid]) ;
+
+                if (!service_resolve_modify_field(&ares[aresid], E_RESOLVE_SERVICE_ENABLED, !action ? "0" : "1"))
+                    log_dieu(LOG_EXIT_SYS, "modify resolve file of: ", ares[aresid].sa.s + ares[aresid].name) ;
+
+                if (!resolve_write_g(wres, ares[aresid].sa.s + ares[aresid].path.home, ares[aresid].sa.s + ares[aresid].name))
+                    log_dieu(LOG_EXIT_SYS, "write  resolve file of: ", ares[aresid].sa.s + ares[aresid].name) ;
 
                 log_info("Disabled successfully service: ", name) ;
 
@@ -110,8 +119,13 @@ void service_enable_disable(graph_t *g, unsigned int idx, resolve_service_t *are
 
                     if (visit[aresid] == VISIT_WHITE) {
 
-                        if (!state_messenger(&ares[aresid], STATE_FLAGS_ISENABLED, !action ? STATE_FLAGS_FALSE : STATE_FLAGS_TRUE))
-                            log_dieusys(LOG_EXIT_SYS, "send message to state of: ", res->sa.s + res->name) ;
+                        wres = resolve_set_struct(DATA_SERVICE, &ares[aresid]) ;
+
+                        if (!service_resolve_modify_field(&ares[aresid], E_RESOLVE_SERVICE_ENABLED, !action ? "0" : "1"))
+                            log_dieu(LOG_EXIT_SYS, "modify resolve file of: ", ares[aresid].sa.s + ares[aresid].name) ;
+
+                        if (!resolve_write_g(wres, ares[aresid].sa.s + ares[aresid].path.home, ares[aresid].sa.s + ares[aresid].name))
+                            log_dieu(LOG_EXIT_SYS, "write  resolve file of: ", ares[aresid].sa.s + ares[aresid].name) ;
 
                         service_enable_disable_deps(g, aresid, ares, areslen, action, visit, propagate) ;
 
@@ -125,6 +139,7 @@ void service_enable_disable(graph_t *g, unsigned int idx, resolve_service_t *are
             }
         }
 
+        free(wres) ;
         visit[idx] = VISIT_GRAY ;
     }
 }
diff --git a/src/lib66/service/service_graph_collect.c b/src/lib66/service/service_graph_collect.c
index f32e2da6..8be348f9 100644
--- a/src/lib66/service/service_graph_collect.c
+++ b/src/lib66/service/service_graph_collect.c
@@ -91,7 +91,7 @@ void service_graph_collect(graph_t *g, char const *alist, size_t alen, resolve_s
 
             if (FLAGS_ISSET(flag, STATE_FLAGS_ISEARLIER)) {
 
-                if (ste.isearlier == STATE_FLAGS_TRUE) {
+                if (res.earlier) {
 
                     if (!service_resolve_copy(&cp, &res))
                         log_dieu(LOG_EXIT_SYS, "copy resolve file of: ", name, " -- please make a bug report") ;
diff --git a/src/lib66/service/service_resolve_copy.c b/src/lib66/service/service_resolve_copy.c
index 648308aa..a92b3812 100644
--- a/src/lib66/service/service_resolve_copy.c
+++ b/src/lib66/service/service_resolve_copy.c
@@ -49,11 +49,11 @@ int service_resolve_copy(resolve_service_t *dst, resolve_service_t *res)
     dst->treename = res->treename ;
     dst->user = res->user ;
     dst->inmodule = res->inmodule ;
+    dst->enabled = res->enabled ;
 
     // path
     dst->path.home = res->path.home ;
     dst->path.frontend = res->path.frontend ;
-    dst->path.status = res->path.status ;
     dst->path.servicedir = res->path.servicedir ;
 
     // dependencies
@@ -86,6 +86,8 @@ int service_resolve_copy(resolve_service_t *dst, resolve_service_t *res)
 
     // live
     dst->live.livedir = res->live.livedir ;
+    dst->live.status = res->live.status ;
+    dst->live.servicedir = res->live.servicedir ;
     dst->live.scandir = res->live.scandir ;
     dst->live.statedir = res->live.statedir ;
     dst->live.eventdir = res->live.eventdir ;
diff --git a/src/lib66/service/service_resolve_get_field_tosa.c b/src/lib66/service/service_resolve_get_field_tosa.c
index 8924a747..3fb6dbe5 100644
--- a/src/lib66/service/service_resolve_get_field_tosa.c
+++ b/src/lib66/service/service_resolve_get_field_tosa.c
@@ -96,6 +96,11 @@ int service_resolve_get_field_tosa(stralloc *sa, resolve_service_t *res, resolve
             str = res->sa.s + res->inmodule ;
             break ;
 
+        case E_RESOLVE_SERVICE_ENABLED:
+            fmt[uint32_fmt(fmt,res->enabled)] = 0 ;
+            str = fmt ;
+            break ;
+
         // path configuration
 
         case E_RESOLVE_SERVICE_HOME:
@@ -106,11 +111,9 @@ int service_resolve_get_field_tosa(stralloc *sa, resolve_service_t *res, resolve
             str = res->sa.s + res->path.frontend ;
             break ;
 
-        case E_RESOLVE_SERVICE_STATUS:
-            str = res->sa.s + res->path.status ;
-
         case E_RESOLVE_SERVICE_SERVICEDIR:
             str = res->sa.s + res->path.servicedir ;
+            break ;
 
         // dependencies
 
@@ -228,6 +231,14 @@ int service_resolve_get_field_tosa(stralloc *sa, resolve_service_t *res, resolve
             str = res->sa.s + res->live.livedir ;
             break ;
 
+        case E_RESOLVE_SERVICE_STATUS:
+            str = res->sa.s + res->live.status ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SERVICEDIR_LIVE:
+            str = res->sa.s + res->live.servicedir ;
+            break ;
+
         case E_RESOLVE_SERVICE_SCANDIR:
             str = res->sa.s + res->live.scandir ;
             break ;
diff --git a/src/lib66/service/service_resolve_modify_field.c b/src/lib66/service/service_resolve_modify_field.c
index 859b8245..abf5e686 100644
--- a/src/lib66/service/service_resolve_modify_field.c
+++ b/src/lib66/service/service_resolve_modify_field.c
@@ -36,11 +36,11 @@ resolve_field_table_t resolve_service_field_table[] = {
     [E_RESOLVE_SERVICE_TREENAME] = { .field = "treename" },
     [E_RESOLVE_SERVICE_USER] = { .field = "user" },
     [E_RESOLVE_SERVICE_INMODULE] = { .field = "inmodule" },
+    [E_RESOLVE_SERVICE_ENABLED] = { .field = "enabled" },
 
     // path
     [E_RESOLVE_SERVICE_HOME] = { .field = "home" },
     [E_RESOLVE_SERVICE_FRONTEND] = { .field = "frontend" },
-    [E_RESOLVE_SERVICE_STATUS] = { .field = "status" },
     [E_RESOLVE_SERVICE_SERVICEDIR] = { .field = "servicedir" },
 
     // dependencies
@@ -73,6 +73,8 @@ resolve_field_table_t resolve_service_field_table[] = {
 
     // live
     [E_RESOLVE_SERVICE_LIVEDIR] = { .field = "livedir" },
+    [E_RESOLVE_SERVICE_STATUS] = { .field = "status" },
+    [E_RESOLVE_SERVICE_SERVICEDIR_LIVE] = { .field = "servicedir" },
     [E_RESOLVE_SERVICE_SCANDIR] = { .field = "scandirdir" },
     [E_RESOLVE_SERVICE_STATEDIR] = { .field = "statedir" },
     [E_RESOLVE_SERVICE_EVENTDIR] = { .field = "eventdir" },
@@ -190,6 +192,11 @@ int service_resolve_modify_field(resolve_service_t *res, resolve_service_enum_t
             res->inmodule = resolve_add_string(wres, data) ;
             break ;
 
+        case E_RESOLVE_SERVICE_ENABLED:
+            res->enabled = resolve_add_uint(data) ; ;
+            break ;
+
+
         // path
 
         case E_RESOLVE_SERVICE_HOME:
@@ -200,10 +207,6 @@ int service_resolve_modify_field(resolve_service_t *res, resolve_service_enum_t
             res->path.frontend = resolve_add_string(wres, data) ;
             break ;
 
-        case E_RESOLVE_SERVICE_STATUS:
-            res->path.status = resolve_add_string(wres, data) ;
-            break ;
-
         case E_RESOLVE_SERVICE_SERVICEDIR:
             res->path.servicedir = resolve_add_string(wres, data) ;
             break ;
@@ -314,6 +317,14 @@ int service_resolve_modify_field(resolve_service_t *res, resolve_service_enum_t
             res->live.livedir = resolve_add_string(wres, data) ;
             break ;
 
+        case E_RESOLVE_SERVICE_STATUS:
+            res->live.status = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SERVICEDIR_LIVE:
+            res->live.servicedir = resolve_add_string(wres, data) ;
+            break ;
+
         case E_RESOLVE_SERVICE_SCANDIR:
             res->live.scandir = resolve_add_string(wres, data) ;
             break ;
diff --git a/src/lib66/service/service_resolve_read_cdb.c b/src/lib66/service/service_resolve_read_cdb.c
index 26c799af..c41705f6 100644
--- a/src/lib66/service/service_resolve_read_cdb.c
+++ b/src/lib66/service/service_resolve_read_cdb.c
@@ -62,15 +62,15 @@ int service_resolve_read_cdb(cdb *c, resolve_service_t *res)
     res->user = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"inmodule") ;
     res->inmodule = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"enabled") ;
+    res->enabled = x ;
 
     /* path configuration */
     resolve_find_cdb(&tmp,c,"home") ;
     res->path.home = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"frontend") ;
     res->path.frontend = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-    resolve_find_cdb(&tmp,c,"status") ;
-    res->path.status = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-    resolve_find_cdb(&tmp,c,"servicedir") ;
+    resolve_find_cdb(&tmp,c,"src_servicedir") ;
     res->path.servicedir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
 
     /* dependencies */
@@ -128,6 +128,10 @@ int service_resolve_read_cdb(cdb *c, resolve_service_t *res)
     /* live */
     resolve_find_cdb(&tmp,c,"livedir") ;
     res->live.livedir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"status") ;
+    res->live.status = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"live_servicedir") ;
+    res->live.servicedir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"scandir") ;
     res->live.scandir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"statedir") ;
diff --git a/src/lib66/service/service_resolve_write_cdb.c b/src/lib66/service/service_resolve_write_cdb.c
index d842ceea..8e9e92ff 100644
--- a/src/lib66/service/service_resolve_write_cdb.c
+++ b/src/lib66/service/service_resolve_write_cdb.c
@@ -41,12 +41,12 @@ int service_resolve_write_cdb(cdbmaker *c, resolve_service_t *sres)
     !resolve_add_cdb(c, "treename", str, sres->treename, 1) ||
     !resolve_add_cdb(c, "user", str, sres->user, 1) ||
     !resolve_add_cdb(c, "inmodule", str, sres->inmodule, 1) ||
+    !resolve_add_cdb_uint(c, "enabled", sres->enabled) ||
 
     // path
     !resolve_add_cdb(c, "home", str, sres->path.home, 1) ||
     !resolve_add_cdb(c, "frontend", str, sres->path.frontend, 1) ||
-    !resolve_add_cdb(c, "status", str, sres->path.status, 1) ||
-    !resolve_add_cdb(c, "servicedir", str, sres->path.servicedir, 1) ||
+    !resolve_add_cdb(c, "src_servicedir", str, sres->path.servicedir, 1) ||
 
     // dependencies
     !resolve_add_cdb(c, "depends", str, sres->dependencies.depends, 1) ||
@@ -78,6 +78,8 @@ int service_resolve_write_cdb(cdbmaker *c, resolve_service_t *sres)
 
     //live
     !resolve_add_cdb(c, "livedir", str, sres->live.livedir, 1) ||
+    !resolve_add_cdb(c, "status", str, sres->live.status, 1) ||
+    !resolve_add_cdb(c, "live_servicedir", str, sres->live.servicedir, 1) ||
     !resolve_add_cdb(c, "scandir", str, sres->live.scandir, 1) ||
     !resolve_add_cdb(c, "statedir", str, sres->live.statedir, 1) ||
     !resolve_add_cdb(c, "eventdir", str, sres->live.eventdir, 1) ||
diff --git a/src/lib66/state/state_check.c b/src/lib66/state/state_check.c
index 9ce829b0..a16c398c 100644
--- a/src/lib66/state/state_check.c
+++ b/src/lib66/state/state_check.c
@@ -26,7 +26,7 @@ int state_check(resolve_service_t *res)
 {
     log_flow() ;
 
-    if (access(res->sa.s + res->path.status, F_OK) < 0)
+    if (access(res->sa.s + res->live.status, F_OK) < 0)
         return 0 ;
 
     return 1 ;
diff --git a/src/lib66/state/state_read.c b/src/lib66/state/state_read.c
index 29c64765..e6a4e209 100644
--- a/src/lib66/state/state_read.c
+++ b/src/lib66/state/state_read.c
@@ -30,7 +30,7 @@ int state_read(ss_state_t *sta, resolve_service_t *res)
     int r ;
     char pack[STATE_STATE_SIZE] ;
 
-    r = openreadnclose(res->sa.s + res->path.status, pack, STATE_STATE_SIZE) ;
+    r = openreadnclose(res->sa.s + res->live.status, pack, STATE_STATE_SIZE) ;
     if (r < STATE_STATE_SIZE || r < 0)
         return 0 ;
 
diff --git a/src/lib66/state/state_rmfile.c b/src/lib66/state/state_rmfile.c
index db6ac989..0acfcf86 100644
--- a/src/lib66/state/state_rmfile.c
+++ b/src/lib66/state/state_rmfile.c
@@ -27,5 +27,5 @@ void state_rmfile(resolve_service_t *res)
 {
     log_flow() ;
 
-    unlink_void(res->sa.s + res->path.status) ;
+    unlink_void(res->sa.s + res->live.status) ;
 }
diff --git a/src/lib66/state/state_write.c b/src/lib66/state/state_write.c
index 894946c5..89b11b57 100644
--- a/src/lib66/state/state_write.c
+++ b/src/lib66/state/state_write.c
@@ -29,22 +29,18 @@ int state_write(ss_state_t *sta, resolve_service_t *res)
 {
     log_flow() ;
 
-    size_t len = strlen(res->sa.s + res->path.home) + SS_SYSTEM_LEN + SS_SERVICE_LEN + SS_SVC_LEN + 1 + strlen(res->sa.s + res->name) ;
     char pack[STATE_STATE_SIZE] ;
-    char dir[len + SS_STATE_LEN + 1] ;
 
-    auto_strings(dir, res->sa.s + res->path.home, SS_SYSTEM, SS_SERVICE, SS_SVC, "/", res->sa.s + res->name, SS_STATE) ;
-
-    if (access(dir, F_OK) < 0) {
-        log_trace("create directory: ", dir) ;
-        if (!dir_create_parent(dir, 0755))
-            log_warnusys_return(LOG_EXIT_ZERO, "create directory: ", dir) ;
+    if (access(res->sa.s + res->live.status, F_OK) < 0) {
+        log_trace("create directory: ", res->sa.s + res->live.status) ;
+        if (!dir_create_parent(res->sa.s + res->live.status, 0755))
+            log_warnusys_return(LOG_EXIT_ZERO, "create directory: ", res->sa.s + res->live.status) ;
     }
 
     state_pack(pack, sta) ;
 
-    log_trace("write status file at: ", res->sa.s + res->path.status) ;
-    if (!openwritenclose_unsafe(res->sa.s + res->path.status, pack, STATE_STATE_SIZE))
+    log_trace("write status file at: ", res->sa.s + res->live.status) ;
+    if (!openwritenclose_unsafe(res->sa.s + res->live.status, pack, STATE_STATE_SIZE))
         return 0 ;
 
     return 1 ;
-- 
GitLab