From 470af2db80704fc93e567b953ad95466e1da3de0 Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Sat, 15 Oct 2022 20:52:19 +1100
Subject: [PATCH] revamp of the resolve struct

---
 src/lib66/service/deps-lib/deps               |  13 +-
 src/lib66/service/service_cmp_basedir.c       |   8 +-
 src/lib66/service/service_frontend_path.c     |  89 ++--
 src/lib66/service/service_frontend_src.c      |  13 +-
 src/lib66/service/service_graph_build.c       |  60 +++
 src/lib66/service/service_graph_collect.c     |  96 ++++
 src/lib66/service/service_graph_g.c           |  30 ++
 src/lib66/service/service_intree.c            | 102 ----
 src/lib66/service/service_is_g.c              | 127 +++++
 src/lib66/service/service_isenabledat.c       | 112 -----
 .../service/service_resolve_array_free.c      |  26 +
 .../service/service_resolve_array_search.c    |  32 ++
 src/lib66/service/service_resolve_copy.c      | 112 +++--
 .../service/service_resolve_from_cmdline.c    |  82 ++++
 .../service/service_resolve_get_field_tosa.c  | 318 ++++++++++---
 .../service/service_resolve_master_copy.c     |   8 +-
 .../service_resolve_master_get_field_tosa.c   |  52 +-
 .../service_resolve_master_modify_field.c     |  96 ++--
 .../service/service_resolve_master_read_cdb.c |  32 +-
 .../service/service_resolve_master_write.c    |  81 ++--
 .../service_resolve_master_write_cdb.c        |  26 +-
 .../service/service_resolve_modify_field.c    | 447 +++++++++++++-----
 src/lib66/service/service_resolve_read_cdb.c  | 257 +++++-----
 .../service/service_resolve_sort_bytype.c     |  13 +-
 src/lib66/service/service_resolve_write.c     |  58 +++
 src/lib66/service/service_resolve_write_cdb.c | 187 ++++----
 26 files changed, 1693 insertions(+), 784 deletions(-)
 create mode 100644 src/lib66/service/service_graph_build.c
 create mode 100644 src/lib66/service/service_graph_collect.c
 create mode 100644 src/lib66/service/service_graph_g.c
 delete mode 100644 src/lib66/service/service_intree.c
 create mode 100644 src/lib66/service/service_is_g.c
 delete mode 100644 src/lib66/service/service_isenabledat.c
 create mode 100644 src/lib66/service/service_resolve_array_free.c
 create mode 100644 src/lib66/service/service_resolve_array_search.c
 create mode 100644 src/lib66/service/service_resolve_from_cmdline.c
 create mode 100644 src/lib66/service/service_resolve_write.c

diff --git a/src/lib66/service/deps-lib/deps b/src/lib66/service/deps-lib/deps
index 138964b8..e1ef2f07 100644
--- a/src/lib66/service/deps-lib/deps
+++ b/src/lib66/service/deps-lib/deps
@@ -1,11 +1,13 @@
-service.o
 service_cmp_basedir.o
 service_endof_dir.o
 service_frontend_path.o
 service_frontend_src.o
-service_intree.o
-service_isenabled.o
-service_isenabledat.o
+service_graph_build.o
+service_graph_collect.o
+service_graph_g.o
+service_is_g.o
+service_resolve_array_free.o
+service_resolve_array_search.o
 service_resolve_copy.o
 service_resolve_get_field_tosa.o
 service_resolve_master_copy.o
@@ -17,9 +19,8 @@ service_resolve_master_write.o
 service_resolve_master_write_cdb.o
 service_resolve_modify_field.o
 service_resolve_read_cdb.o
-service_resolve_setlognwrite.o
-service_resolve_setnwrite.o
 service_resolve_sort_bytype.o
+service_resolve_write.o
 service_resolve_write_cdb.o
 -loblibs
 -lskarnet
diff --git a/src/lib66/service/service_cmp_basedir.c b/src/lib66/service/service_cmp_basedir.c
index 245021dc..b9bbc757 100644
--- a/src/lib66/service/service_cmp_basedir.c
+++ b/src/lib66/service/service_cmp_basedir.c
@@ -29,6 +29,8 @@ int service_cmp_basedir(char const *dir)
 
     /** dir can be 0, so nothing to do */
     if (!dir) return 1 ;
+
+    int e = 0 ;
     size_t len = strlen(dir) ;
     uid_t owner = MYUID ;
     stralloc home = STRALLOC_ZERO ;
@@ -65,9 +67,9 @@ int service_cmp_basedir(char const *dir)
                     goto err ;
             } else goto err ;
 
-    stralloc_free(&home) ;
-    return 1 ;
+    e = 1 ;
+
     err:
         stralloc_free(&home) ;
-        return 0 ;
+        return e ;
 }
diff --git a/src/lib66/service/service_frontend_path.c b/src/lib66/service/service_frontend_path.c
index 4b24b173..4429cf45 100644
--- a/src/lib66/service/service_frontend_path.c
+++ b/src/lib66/service/service_frontend_path.c
@@ -15,60 +15,75 @@
 #include <sys/types.h>
 
 #include <oblibs/log.h>
+#include <oblibs/string.h>
 
 #include <skalibs/stralloc.h>
 
+#include <66/config.h>
 #include <66/utils.h>
 #include <66/constants.h>
 #include <66/service.h>
 
-int service_frontend_path(stralloc *sasrc,char const *sv, uid_t owner,char const *directory_forced)
+int service_frontend_path(stralloc *sasrc, char const *sv, uid_t owner, char const *directory_forced)
 {
     log_flow() ;
 
-    int r ;
+    int r, e = 0 ;
     char const *src = 0 ;
-    int err = -1 ;
-    stralloc home = STRALLOC_ZERO ;
-    if (directory_forced)
-    {
-        if (!service_cmp_basedir(directory_forced)) { log_warn("invalid base service directory: ",directory_forced) ; goto err ; }
+    char home[SS_MAX_PATH_LEN + 1 + strlen(SS_USER_DIR) + 1] ;
+
+    if (directory_forced) {
+
+        if (!service_cmp_basedir(directory_forced))
+            log_die(LOG_EXIT_USER, "invalid base service directory: ", directory_forced) ;
+
         src = directory_forced ;
-        r = service_frontend_src(sasrc,sv,src) ;
-        if (r == -1){ log_warnusys("parse source directory: ",src) ; goto err ; }
-        if (!r) { log_warnu("find service: ",sv) ; err = 0 ; goto err ; }
-    }
-    else
-    {
-        if (!owner) src = SS_SERVICE_ADMDIR ;
-        else
-        {
-            if (!set_ownerhome(&home,owner)) { log_warnusys("set home directory") ; goto err ; }
-            if (!stralloc_cats(&home,SS_SERVICE_USERDIR)) { log_warnsys("stralloc") ; goto err ; }
-            if (!stralloc_0(&home)) { log_warnsys("stralloc") ; goto err ; }
-            home.len-- ;
-            src = home.s ;
-        }
+        r = service_frontend_src(sasrc, sv, src) ;
+        if (r == -1)
+            log_dieusys(LOG_EXIT_SYS, "parse source directory: ", src) ;
 
-        r = service_frontend_src(sasrc,sv,src) ;
-        if (r == -1){ log_warnusys("parse source directory: ",src) ; goto err ; }
         if (!r)
-        {
+            goto freed ;
+
+    } else {
+
+        if (!owner)
             src = SS_SERVICE_ADMDIR ;
-            r = service_frontend_src(sasrc,sv,src) ;
-            if (r == -1) { log_warnusys("parse source directory: ",src) ; goto err ; }
-            if (!r)
-            {
+        else {
+
+            if (!set_ownerhome_stack(home))
+                log_dieusys(LOG_EXIT_SYS, "set home directory") ;
+
+            auto_strings(home + strlen(home), SS_USER_DIR) ;
+
+            src = home ;
+        }
+
+        r = service_frontend_src(sasrc, sv, src) ;
+        if (r == -1)
+            log_dieusys(LOG_EXIT_SYS, "parse source directory: ", src) ;
+
+        if (!r) {
+
+            src = SS_SERVICE_ADMDIR ;
+            r = service_frontend_src(sasrc, sv, src) ;
+            if (r == -1)
+                log_dieusys(LOG_EXIT_SYS, "parse source directory: ", src) ;
+
+            if (!r) {
+
                 src = SS_SERVICE_SYSDIR ;
-                r = service_frontend_src(sasrc,sv,src) ;
-                if (r == -1) { log_warnusys("parse source directory: ",src) ; goto err ; }
-                if (!r) { log_warnu("find service: ",sv) ; err = 0 ; goto err ; }
+                r = service_frontend_src(sasrc, sv, src) ;
+                if (r == -1)
+                    log_dieusys(LOG_EXIT_SYS, "parse source directory: ", src) ;
+
+                if (!r)
+                    goto freed ;
             }
         }
     }
-    stralloc_free(&home) ;
-    return 1 ;
-    err:
-        stralloc_free(&home) ;
-        return err ;
+    e = 1 ;
+
+    freed:
+        return e ;
 }
diff --git a/src/lib66/service/service_frontend_src.c b/src/lib66/service/service_frontend_src.c
index 30e4dbdd..8f8ecbc1 100644
--- a/src/lib66/service/service_frontend_src.c
+++ b/src/lib66/service/service_frontend_src.c
@@ -31,14 +31,23 @@ int service_frontend_src(stralloc *sasrc, char const *name, char const *src)
 
     int  insta, equal = 0, e = -1, r = 0, found = 0 ;
     stralloc sa = STRALLOC_ZERO ;
-    size_t pos = 0, dpos = 0 ;
+    size_t pos = 0, dpos = 0, pathlen = strlen(src) ;
 
     char const *exclude[1] = { 0 } ;
 
-    if (!sastr_dir_get_recursive(&sa, src, exclude, S_IFREG|S_IFDIR, 1)) {
+    char path[pathlen + 1] ;
+
+    auto_strings(path, src) ;
+
+    /** avoid double slash */
+    if (path[pathlen - 1] == '/')
+        path[pathlen - 1] = 0 ;
+
+    if (!sastr_dir_get_recursive(&sa, path, exclude, S_IFREG|S_IFDIR, 1)) {
         stralloc_free(&sa) ;
         return e ;
     }
+
     size_t len = sa.len ;
     char tmp[len + 1] ;
     sastr_to_char(tmp, &sa) ;
diff --git a/src/lib66/service/service_graph_build.c b/src/lib66/service/service_graph_build.c
new file mode 100644
index 00000000..c04bbb1c
--- /dev/null
+++ b/src/lib66/service/service_graph_build.c
@@ -0,0 +1,60 @@
+/*
+ * service_graph_build.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdint.h>
+
+#include <oblibs/log.h>
+#include <oblibs/types.h>
+#include <oblibs/graph.h>
+
+#include <66/service.h>
+#include <66/graph.h>
+#include <66/state.h>
+
+void service_graph_build(graph_t *g, resolve_service_t *ares, unsigned int areslen, uint32_t flag)
+{
+    log_flow() ;
+
+    unsigned int pos = 0 ;
+    resolve_service_t_ref pres = 0 ;
+
+    for (; pos < areslen ; pos++) {
+
+        pres = &ares[pos] ;
+        char *service = pres->sa.s + pres->name ;
+
+        if (!graph_vertex_add(g, service))
+            log_dieu(LOG_EXIT_SYS, "add vertex: ", service) ;
+
+        if (FLAGS_ISSET(flag, STATE_FLAGS_TOPROPAGATE)) {
+
+            if (pres->dependencies.ndepends && FLAGS_ISSET(flag, STATE_FLAGS_WANTUP))
+                if (!graph_compute_dependencies(g, service, pres->sa.s + pres->dependencies.depends, 0))
+                    log_dieu(LOG_EXIT_SYS, "add dependencies of service: ",service) ;
+
+            if (pres->dependencies.nrequiredby && FLAGS_ISSET(flag, STATE_FLAGS_WANTDOWN))
+                if (!graph_compute_dependencies(g, service, pres->sa.s + pres->dependencies.requiredby, 1))
+                    log_dieu(LOG_EXIT_SYS, "add dependencies of service: ",service) ;
+        }
+    }
+
+    if (!graph_matrix_build(g))
+        log_dieu(LOG_EXIT_SYS, "build the graph") ;
+
+    if (!graph_matrix_analyze_cycle(g))
+        log_dieu(LOG_EXIT_SYS, "found cycle") ;
+
+    if (!graph_matrix_sort(g))
+        log_dieu(LOG_EXIT_SYS, "sort the graph") ;
+}
diff --git a/src/lib66/service/service_graph_collect.c b/src/lib66/service/service_graph_collect.c
new file mode 100644
index 00000000..6ad9312d
--- /dev/null
+++ b/src/lib66/service/service_graph_collect.c
@@ -0,0 +1,96 @@
+/*
+ * service_graph_collect.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+#include <oblibs/types.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/service.h>
+#include <66/resolve.h>
+#include <66/sanitize.h>
+#include <66/state.h>
+#include <66/graph.h>
+#include <66/enum.h>
+
+/** list all services of the system
+ * STATE_FLAGS_TOINIT -> it call sanitize_source() function.
+ * STATE_FLAGS_TOPROPAGATE -> it build with the dependencies/requiredby services.
+ * STATE_FLAGS_ISSUPERVISED -> only keep already supervised service*/
+void service_graph_collect(graph_t *g, char const *alist, size_t alen, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint32_t flag)
+{
+    log_flow () ;
+
+    size_t pos = 0 ;
+    ss_state_t ste = STATE_ZERO ;
+    stralloc sa = STRALLOC_ZERO ;
+
+    resolve_wrapper_t_ref wres = 0 ;
+
+    for (; pos < alen ; pos += strlen(alist + pos) + 1) {
+
+        sa.len = 0 ;
+        char const *name = alist + pos ;
+
+        if (service_resolve_array_search(ares, (*areslen), name) < 0) {
+
+            resolve_service_t res = RESOLVE_SERVICE_ZERO ;
+            wres = resolve_set_struct(DATA_SERVICE, &res) ;
+
+            if (FLAGS_ISSET(flag, STATE_FLAGS_TOINIT))
+                sanitize_source(name, info, flag) ;
+
+            if (!resolve_read_g(wres, info->base.s, name))
+                log_dieu(LOG_EXIT_SYS, "read resolve file of: ", name, " -- please make a bug report") ;
+
+            if (FLAGS_ISSET(flag, STATE_FLAGS_ISSUPERVISED)) {
+
+                if (!state_read(&ste, res.sa.s + res.path.home, name))
+                    log_dieu(LOG_EXIT_SYS, "read state file of: ", name, " -- please make a bug report") ;
+
+                if (service_is(&ste, STATE_FLAGS_ISSUPERVISED))
+                    ares[(*areslen)++] = res ;
+                else
+                    continue ;
+            } else
+                ares[(*areslen)++] = res ;
+
+            if (FLAGS_ISSET(flag, STATE_FLAGS_TOPROPAGATE)) {
+
+                if (res.dependencies.ndepends && FLAGS_ISSET(flag, STATE_FLAGS_WANTDOWN)) {
+
+                    if (!sastr_clean_string(&sa, res.sa.s + res.dependencies.depends))
+                        log_dieu(LOG_EXIT_SYS, "clean string") ;
+
+                    service_graph_collect(g, sa.s, sa.len, ares, areslen, info, flag) ;
+
+                } else if (res.dependencies.nrequiredby && FLAGS_ISSET(flag, STATE_FLAGS_WANTUP)) {
+
+                    if (!sastr_clean_string(&sa, res.sa.s + res.dependencies.requiredby))
+                        log_dieu(LOG_EXIT_SYS, "clean string") ;
+
+                    service_graph_collect(g, sa.s, sa.len, ares, areslen, info, flag) ;
+                }
+            }
+        }
+    }
+
+    free(wres) ;
+    stralloc_free(&sa) ;
+}
diff --git a/src/lib66/service/service_graph_g.c b/src/lib66/service/service_graph_g.c
new file mode 100644
index 00000000..5c90595a
--- /dev/null
+++ b/src/lib66/service/service_graph_g.c
@@ -0,0 +1,30 @@
+/*
+ * service_graph_g.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdint.h>
+
+#include <oblibs/log.h>
+
+#include <66/service.h>
+#include <66/graph.h>
+#include <66/ssexec.h>
+
+void service_graph_g(char const *alist, size_t alen, graph_t *graph, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint32_t flag)
+{
+    log_flow() ;
+
+    service_graph_collect(graph, alist, alen, ares, areslen, info, flag) ;
+
+    service_graph_build(graph, ares, (*areslen), flag) ;
+}
diff --git a/src/lib66/service/service_intree.c b/src/lib66/service/service_intree.c
deleted file mode 100644
index 7e822c4c..00000000
--- a/src/lib66/service/service_intree.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * service_intree.c
- *
- * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
- *
- * All rights reserved.
- *
- * This file is part of Obarun. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution.
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file./
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <oblibs/log.h>
-#include <oblibs/string.h>
-#include <oblibs/types.h>
-#include <oblibs/sastr.h>
-
-#include <skalibs/stralloc.h>
-
-#include <66/constants.h>
-#include <66/resolve.h>
-#include <66/utils.h>
-#include <66/service.h>
-
-/** @Return -1 system error
- * @Return 0 no tree exist yet
- * @Return 1 svname doesn't exist
- * @Return 2 on success
- * @Return > 2, service exist on different tree */
-int service_intree(stralloc *svtree, char const *svname, char const *tree)
-{
-    log_flow() ;
-
-    uint8_t found = 1, copied = 0 ;
-    uid_t owner = getuid() ;
-    size_t pos = 0, newlen ;
-    stralloc satree = STRALLOC_ZERO ;
-    stralloc tmp = STRALLOC_ZERO ;
-    char const *exclude[3] = { SS_BACKUP + 1, SS_RESOLVE + 1, 0 } ;
-
-    if (!set_ownersysdir(svtree,owner)) { log_warnusys("set owner directory") ; goto err ; }
-    if (!auto_stra(svtree,SS_SYSTEM)) goto err ;
-
-    if (!scan_mode(svtree->s,S_IFDIR))
-    {
-        found = 0 ;
-        goto freed ;
-    }
-
-    if (!auto_stra(svtree,"/")) goto err ;
-    newlen = svtree->len ;
-
-    if (!stralloc_copy(&tmp,svtree)) goto err ;
-
-    if (!sastr_dir_get(&satree, svtree->s, exclude, S_IFDIR)) {
-        log_warnu("get list of trees from directory: ",svtree->s) ;
-        goto err ;
-    }
-
-    if (satree.len)
-    {
-
-        FOREACH_SASTR(&satree, pos) {
-
-            tmp.len = newlen ;
-            char *name = satree.s + pos ;
-
-            if (!auto_stra(&tmp,name,SS_SVDIRS)) goto err ;
-            if (resolve_check(tmp.s,svname)) {
-
-                if (!tree || (tree && !strcmp(name,tree))){
-                    svtree->len = 0 ;
-                    if (!stralloc_copy(svtree,&tmp)) goto err ;
-                    copied = 1 ;
-                }
-                found++ ;
-            }
-        }
-    }
-    else
-    {
-        found = 0 ;
-        goto freed ;
-    }
-
-    if (found > 2 && tree) found = 2 ;
-    if (!copied) found = 1 ;
-    if (!stralloc_0(svtree)) goto err ;
-    freed:
-    stralloc_free(&satree) ;
-    stralloc_free(&tmp) ;
-    return found ;
-    err:
-        stralloc_free(&satree) ;
-        stralloc_free(&tmp) ;
-        return -1 ;
-}
diff --git a/src/lib66/service/service_is_g.c b/src/lib66/service/service_is_g.c
new file mode 100644
index 00000000..0092606b
--- /dev/null
+++ b/src/lib66/service/service_is_g.c
@@ -0,0 +1,127 @@
+/*
+ * service_is_g.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/service.h>
+#include <66/tree.h>
+#include <66/resolve.h>
+#include <66/state.h>
+#include <66/constants.h>
+#include <66/utils.h>
+
+int service_is(ss_state_t *ste, uint32_t flag)
+{
+
+    switch (flag) {
+
+        case STATE_FLAGS_TOINIT : return FLAGS_ISSET(ste->toinit, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_TORELOAD: return FLAGS_ISSET(ste->toreload, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_TORESTART : return FLAGS_ISSET(ste->torestart, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_TOUNSUPERVISE : return FLAGS_ISSET(ste->tounsupervise, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_ISDOWNFILE : return FLAGS_ISSET(ste->isdownfile, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_ISEARLIER : return FLAGS_ISSET(ste->isearlier, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_ISENABLED : return FLAGS_ISSET(ste->isenabled, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_ISPARSED : return  FLAGS_ISSET(ste->isparsed, STATE_FLAGS_TRUE) ; //always true framboise
+
+        case STATE_FLAGS_ISSUPERVISED : return FLAGS_ISSET(ste->issupervised, STATE_FLAGS_TRUE) ;
+
+        case STATE_FLAGS_ISUP : return FLAGS_ISSET(ste->isup, STATE_FLAGS_TRUE) ;
+
+        default:
+            break ;
+
+    }
+
+    return 0 ;
+}
+
+/*@Return :
+ * -1 system error
+ * 0 check fail
+ * 1 check success */
+int service_is_g(char *atree, char const *name, uint32_t flag)
+{
+
+    log_flow() ;
+
+    ss_state_t ste = STATE_ZERO ;
+    resolve_service_t res = RESOLVE_SERVICE_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ;
+    int e = -1, r = -1 ;
+    char base[SS_MAX_PATH_LEN + SS_SYSTEM_LEN + 1] ;
+
+    if (!set_ownersysdir_stack(base, getuid())) {
+
+        log_warnusys("set owner directory") ;
+        resolve_free(wres) ;
+        return e ;
+    }
+
+    size_t baselen = strlen(base) ;
+    //char tmp[baselen + SS_SYSTEM_LEN + 1] ;
+    auto_strings(base + baselen, SS_SYSTEM) ;
+
+    // no tree exist yet
+    if (!scan_mode(base, S_IFDIR)) {
+        e = 0 ;
+        goto freed ;
+    }
+
+    base[baselen] = 0 ;
+
+    r = resolve_read_g(wres, base, name) ;
+    if (r == -1)
+        goto freed ;
+    else if (!r) {
+        e = 0 ;
+        goto freed ;
+    }
+
+    if (strlen(res.sa.s + res.treename) > SS_MAX_TREENAME) {
+        errno = ENAMETOOLONG ;
+        goto freed ;
+    }
+
+    auto_strings(atree, res.sa.s + res.treename) ;
+
+    if (!state_read(&ste, res.sa.s + res.path.home, name)) {
+        log_warnu("read state file of: ", name, " -- please make a bug report") ;
+        goto freed ;
+    }
+
+    e = service_is(&ste, flag) ;
+
+    freed:
+        resolve_free(wres) ;
+        return e ;
+}
+
+
diff --git a/src/lib66/service/service_isenabledat.c b/src/lib66/service/service_isenabledat.c
deleted file mode 100644
index df4405fe..00000000
--- a/src/lib66/service/service_isenabledat.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * service_isenabledat.c
- *
- * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
- *
- * All rights reserved.
- *
- * This file is part of Obarun. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution.
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file./
- */
-
-#include <stddef.h>
-
-#include <oblibs/log.h>
-#include <oblibs/string.h>
-#include <oblibs/types.h>
-#include <oblibs/sastr.h>
-
-#include <skalibs/stralloc.h>
-
-#include <66/constants.h>
-#include <66/resolve.h>
-#include <66/utils.h>
-#include <66/service.h>
-
-/** @Return 0 if not found
- * @Return 1 if found
- * @Return 2 if found but marked disabled
- * @Return -1 system error */
-int service_isenabledat(char *atree, char const *sv)
-{
-
-    log_flow() ;
-
-    stralloc sa = STRALLOC_ZERO ;
-    resolve_service_t res = RESOLVE_SERVICE_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ;
-    size_t newlen = 0, pos = 0 ;
-    int e = -1, r ;
-    char const *exclude[3] = { SS_BACKUP + 1, SS_RESOLVE + 1, 0 } ;
-
-    if (!set_ownersysdir(&sa, getuid())) {
-
-        log_warnusys("set owner directory") ;
-        stralloc_free(&sa) ;
-        return 0 ;
-    }
-
-    char tmp[sa.len + SS_SYSTEM_LEN + 2] ;
-    auto_strings(tmp, sa.s, SS_SYSTEM) ;
-
-    // no tree exist yet
-    if (!scan_mode(tmp, S_IFDIR))
-        goto empty ;
-
-    auto_strings(tmp, sa.s, SS_SYSTEM, "/") ;
-
-    newlen = sa.len + SS_SYSTEM_LEN + 1 ;
-    sa.len = 0 ;
-
-    if (!sastr_dir_get(&sa, tmp, exclude, S_IFDIR)) {
-
-        log_warnu("get list of trees from: ", tmp) ;
-        goto freed ;
-    }
-
-    FOREACH_SASTR(&sa, pos) {
-
-        char *treename = sa.s + pos ;
-
-        char trees[newlen + strlen(treename) + SS_SVDIRS_LEN + 1] ;
-        auto_strings(trees, tmp, treename, SS_SVDIRS) ;
-
-
-        r = resolve_read_g(wres, trees, sv) ;
-
-        if (r < 0) {
-
-            log_warnu("read resolve file: ", trees, "/", sv) ;
-            e = -1 ;
-            goto freed ;
-
-        } else if (r) {
-
-            if (res.disen) {
-
-                log_trace(sv, " enabled at tree: ", treename) ;
-                e = 1 ;
-
-            } else {
-
-                log_trace(sv, " disabled at tree: ", treename) ;
-                e = 2 ;
-            }
-
-            if (!auto_strings(atree, treename)) {
-                e = -1 ;
-                goto freed ;
-            }
-            goto freed ;
-        }
-    }
-    empty:
-        e = 0 ;
-    freed:
-        stralloc_free(&sa) ;
-        resolve_free(wres) ;
-        return e ;
-}
diff --git a/src/lib66/service/service_resolve_array_free.c b/src/lib66/service/service_resolve_array_free.c
new file mode 100644
index 00000000..14f94dbb
--- /dev/null
+++ b/src/lib66/service/service_resolve_array_free.c
@@ -0,0 +1,26 @@
+/*
+ * service_resolve_array_free.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <skalibs/stralloc.h>
+
+#include <66/service.h>
+
+void service_resolve_array_free(resolve_service_t *ares, unsigned int areslen)
+{
+
+    unsigned int pos = 0 ;
+    for (; pos < areslen ; pos++)
+        stralloc_free(&ares[pos].sa) ;
+}
+
diff --git a/src/lib66/service/service_resolve_array_search.c b/src/lib66/service/service_resolve_array_search.c
new file mode 100644
index 00000000..12fd1092
--- /dev/null
+++ b/src/lib66/service/service_resolve_array_search.c
@@ -0,0 +1,32 @@
+/*
+ * service_resolve_array_search.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <66/service.h>
+
+int service_resolve_array_search(resolve_service_t *ares, unsigned int areslen, char const *name)
+{
+    unsigned int pos = 0 ;
+
+    for (; pos < areslen ; pos++) {
+
+        char const *n = ares[pos].sa.s + ares[pos].name ;
+            if (!strcmp(name, n))
+                return pos ;
+    }
+
+    return -1 ;
+}
+
diff --git a/src/lib66/service/service_resolve_copy.c b/src/lib66/service/service_resolve_copy.c
index bd5f5866..737767a4 100644
--- a/src/lib66/service/service_resolve_copy.c
+++ b/src/lib66/service/service_resolve_copy.c
@@ -34,39 +34,93 @@ int service_resolve_copy(resolve_service_t *dst, resolve_service_t *res)
         !stralloc_0(&dst->sa))
             return 0 ;
 
+    // configuration
     dst->name = res->name ;
     dst->description = res->description ;
     dst->version = res->version ;
-    dst->logger = res->logger ;
-    dst->logreal = res->logreal ;
-    dst->logassoc = res->logassoc ;
-    dst->dstlog = res->dstlog ;
-    dst->depends = res->depends ;
-    dst->requiredby = res->requiredby ;
-    dst->optsdeps = res->optsdeps ;
-    dst->extdeps = res->extdeps ;
-    dst->contents = res->contents ;
-    dst->src = res->src ;
-    dst->srconf = res->srconf ;
-    dst->live = res->live ;
-    dst->runat = res->runat ;
-    dst->tree = res->tree ;
-    dst->treename = res->treename ;
-    dst->state = res->state ;
-    dst->exec_run = res->exec_run ;
-    dst->exec_log_run = res->exec_log_run ;
-    dst->real_exec_run = res->real_exec_run ;
-    dst->real_exec_log_run = res->real_exec_log_run ;
-    dst->exec_finish = res->exec_finish ;
-    dst->real_exec_finish = res->real_exec_finish ;
     dst->type = res->type ;
-    dst->ndepends = res->ndepends ;
-    dst->nrequiredby = res->nrequiredby ;
-    dst->noptsdeps = res->noptsdeps ;
-    dst->nextdeps = res->nextdeps ;
-    dst->ncontents = res->ncontents ;
-    dst->down = res->down ;
-    dst->disen = res->disen ;
+    dst->notify = res->notify ;
+    dst->maxdeath = res->maxdeath ;
+    dst->earlier = res->earlier ;
+    dst->hiercopy = res->hiercopy ;
+    dst->intree = res->intree ;
+    dst->ownerstr = res->ownerstr ;
+    dst->owner = res->owner ;
+    dst->treename = res->treename ;
+    dst->user = res->user ;
+    dst->inmodule = res->inmodule ;
+
+    // path
+    dst->path.home = res->path.home ;
+    dst->path.frontend = res->path.frontend ;
+    dst->path.tree = res->path.tree ;
+    dst->path.status = res->path.status ;
+
+    // dependencies
+    dst->dependencies.depends = res->dependencies.depends ;
+    dst->dependencies.requiredby = res->dependencies.requiredby ;
+    dst->dependencies.optsdeps = res->dependencies.optsdeps ;
+    dst->dependencies.ndepends = res->dependencies.ndepends ;
+    dst->dependencies.nrequiredby = res->dependencies.nrequiredby ;
+    dst->dependencies.noptsdeps = res->dependencies.noptsdeps ;
+
+    // execute
+    dst->execute.run.run = res->execute.run.run ;
+    dst->execute.run.run_user = res->execute.run.run_user ;
+    dst->execute.run.build = res->execute.run.build ;
+    dst->execute.run.shebang = res->execute.run.shebang ;
+    dst->execute.run.runas = res->execute.run.runas ;
+    dst->execute.finish.run = res->execute.finish.run ;
+    dst->execute.finish.run_user = res->execute.finish.run_user ;
+    dst->execute.finish.build = res->execute.finish.build ;
+    dst->execute.finish.shebang = res->execute.finish.shebang ;
+    dst->execute.finish.runas = res->execute.finish.runas ;
+    dst->execute.timeout.kill = res->execute.timeout.kill ;
+    dst->execute.timeout.finish = res->execute.timeout.finish ;
+    dst->execute.timeout.up = res->execute.timeout.up ;
+    dst->execute.timeout.down = res->execute.timeout.down ;
+    dst->execute.down = res->execute.down ;
+    dst->execute.downsignal = res->execute.downsignal ;
+
+    // live
+    dst->live.livedir = res->live.livedir ;
+    dst->live.scandir = res->live.scandir ;
+    dst->live.statedir = res->live.statedir ;
+    dst->live.eventdir = res->live.eventdir ;
+    dst->live.notifdir = res->live.notifdir ;
+    dst->live.supervisedir = res->live.supervisedir ;
+    dst->live.fdholderdir = res->live.fdholderdir ;
+    dst->live.oneshotddir = res->live.oneshotddir ;
+
+    // logger
+    dst->logger.name = res->logger.name ;
+    dst->logger.destination = res->logger.destination ;
+    dst->logger.backup = res->logger.backup ;
+    dst->logger.maxsize = res->logger.maxsize ;
+    dst->logger.timestamp = res->logger.timestamp ;
+    dst->logger.want = res->logger.want ;
+    dst->logger.execute.run.run = res->logger.execute.run.run ;
+    dst->logger.execute.run.run_user = res->logger.execute.run.run_user ;
+    dst->logger.execute.run.build = res->logger.execute.run.build ;
+    dst->logger.execute.run.shebang = res->logger.execute.run.shebang ;
+    dst->logger.execute.run.runas = res->logger.execute.run.runas ;
+    dst->logger.timeout.kill = res->logger.timeout.kill ;
+    dst->logger.timeout.finish = res->logger.timeout.finish ;
+
+    // environment
+    dst->environ.env = res->environ.env ;
+    dst->environ.envdir = res->environ.envdir ;
+    dst->environ.env_overwrite = res->environ.env_overwrite ;
+
+    // regex
+    dst->regex.configure = res->regex.configure ;
+    dst->regex.directories = res->regex.directories ;
+    dst->regex.files = res->regex.files ;
+    dst->regex.infiles = res->regex.infiles ;
+    dst->regex.ndirectories = res->regex.ndirectories ;
+    dst->regex.nfiles = res->regex.nfiles ;
+    dst->regex.ninfiles = res->regex.ninfiles ;
+
 
     return 1 ;
 }
diff --git a/src/lib66/service/service_resolve_from_cmdline.c b/src/lib66/service/service_resolve_from_cmdline.c
new file mode 100644
index 00000000..0e1c6b27
--- /dev/null
+++ b/src/lib66/service/service_resolve_from_cmdline.c
@@ -0,0 +1,82 @@
+/*
+ * resolve_from_cmdline.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdint.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/graph.h>
+
+#include <skalibs/genalloc.h>
+
+#include <66/resolve.h>
+#include <66/service.h>
+#include <66/graph.h>
+#include <66/ssexec.h>
+#include <66/constants.h>
+
+int service_resolve_from_cmdline(resolve_service_t *ares, graph_t *graph, ssexec_t *info, char const *const *argv, uint8_t requiredby)
+{
+
+    resolve_service_t res = RESOLVE_SERVICE_ZERO ;
+    resolve_wrapper_t_ref wres = 0 ;
+    unsigned int areslen = 0 ;
+
+    for (; *argv ; argv++) {
+
+        unsigned int pos = 0, *alist = 0, ndeps = 0 ;
+        char const *name = *argv ;
+
+        wres = resolve_set_struct(DATA_SERVICE, &res) ;
+
+        if (resolve_read_g(wres, info->base.s, name) <= 0)
+            log_dieusys(LOG_EXIT_SYS,"read resolve file of: ", name) ;
+
+        resolve_service_t cp = RESOLVE_SERVICE_ZERO ;
+
+        if (!service_resolve_copy(&cp, &res))
+            log_dieusys(LOG_EXIT_SYS,"copy resolve file of: ", name) ;
+
+        if (service_resolve_array_search(ares, areslen, name) < 0)
+            ares[areslen++] = cp ;
+
+        ndeps = graph_matrix_get_edge_g_list(alist, graph, name, requiredby, 1) ;
+
+        if (ndeps < 0)
+            log_dieu(LOG_EXIT_SYS, "get dependencies of service: ", name) ;
+
+        for (; pos < ndeps ; pos++) {
+
+            char *name = graph->data.s + genalloc_s(graph_hash_t, &graph->hash)[alist[pos]].vertex ;
+
+            resolve_service_t dres = RESOLVE_SERVICE_ZERO ;
+            wres = resolve_set_struct(DATA_SERVICE, &dres) ;
+
+            if (!service_resolve_array_search(ares, areslen, name)) {
+
+                if (resolve_read_g(wres, info->base.s, name) <= 0)
+                    log_dieusys(LOG_EXIT_SYS,"read resolve file of: ",name) ;
+
+                ares[areslen++] = dres ;
+            }
+
+            resolve_free(wres) ;
+        }
+
+        resolve_free(wres) ;
+    }
+
+
+    return areslen ;
+}
diff --git a/src/lib66/service/service_resolve_get_field_tosa.c b/src/lib66/service/service_resolve_get_field_tosa.c
index 7044dab5..f6a6e0e8 100644
--- a/src/lib66/service/service_resolve_get_field_tosa.c
+++ b/src/lib66/service/service_resolve_get_field_tosa.c
@@ -29,155 +29,341 @@ int service_resolve_get_field_tosa(stralloc *sa, resolve_service_t *res, resolve
 
     char fmt[UINT32_FMT] ;
     char const *str = 0 ;
+    int e = 0 ;
 
     switch(field) {
 
-        case SERVICE_ENUM_NAME:
+        // configuration
+
+        case E_RESOLVE_SERVICE_NAME:
             str = res->sa.s + res->name ;
             break ;
 
-        case SERVICE_ENUM_DESCRIPTION:
+        case E_RESOLVE_SERVICE_DESCRIPTION:
             str = res->sa.s + res->description ;
             break ;
 
-        case SERVICE_ENUM_VERSION:
+        case E_RESOLVE_SERVICE_VERSION:
             str = res->sa.s + res->version ;
             break ;
 
-        case SERVICE_ENUM_LOGGER:
-            str = res->sa.s + res->logger ;
+        case E_RESOLVE_SERVICE_TYPE:
+            fmt[uint32_fmt(fmt,res->type)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_LOGREAL:
-            str = res->sa.s + res->logreal ;
+        case E_RESOLVE_SERVICE_NOTIFY:
+            fmt[uint32_fmt(fmt,res->notify)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_LOGASSOC:
-            str = res->sa.s + res->logassoc ;
+        case E_RESOLVE_SERVICE_MAXDEATH:
+            fmt[uint32_fmt(fmt,res->maxdeath)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_DSTLOG:
-            str = res->sa.s + res->dstlog ;
+        case E_RESOLVE_SERVICE_EARLIER:
+            fmt[uint32_fmt(fmt,res->earlier)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_DEPENDS:
-            str = res->sa.s + res->depends ;
+        case E_RESOLVE_SERVICE_HIERCOPY:
+            str = res->sa.s + res->hiercopy ;
             break ;
 
-        case SERVICE_ENUM_REQUIREDBY:
-            str = res->sa.s + res->requiredby ;
+        case E_RESOLVE_SERVICE_INTREE:
+            str = res->sa.s + res->intree ;
             break ;
 
-        case SERVICE_ENUM_OPTSDEPS:
-            str = res->sa.s + res->optsdeps ;
+        case E_RESOLVE_SERVICE_OWNERSTR:
+            str = res->sa.s + res->ownerstr ;
             break ;
 
-        case SERVICE_ENUM_EXTDEPS:
-            str = res->sa.s + res->extdeps ;
+        case E_RESOLVE_SERVICE_OWNER:
+            fmt[uint32_fmt(fmt,res->owner)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_CONTENTS:
-            str = res->sa.s + res->contents ;
+        case E_RESOLVE_SERVICE_TREENAME:
+            str = res->sa.s + res->treename ;
             break ;
 
-        case SERVICE_ENUM_SRC:
-            str = res->sa.s + res->src ;
+        case E_RESOLVE_SERVICE_USER:
+            str = res->sa.s + res->user ;
             break ;
 
-        case SERVICE_ENUM_SRCONF:
-            str = res->sa.s + res->srconf ;
+        case E_RESOLVE_SERVICE_INMODULE:
+            str = res->sa.s + res->inmodule ;
             break ;
 
-        case SERVICE_ENUM_LIVE:
-            str = res->sa.s + res->live ;
+        // path configuration
+
+        case E_RESOLVE_SERVICE_HOME:
+            str = res->sa.s + res->path.home ;
             break ;
 
-        case SERVICE_ENUM_RUNAT:
-            str = res->sa.s + res->runat ;
+        case E_RESOLVE_SERVICE_FRONTEND:
+            str = res->sa.s + res->path.frontend ;
             break ;
 
-        case SERVICE_ENUM_TREE:
-            str = res->sa.s + res->tree ;
+        case E_RESOLVE_SERVICE_TREE:
+            str = res->sa.s + res->path.tree ;
             break ;
 
-        case SERVICE_ENUM_TREENAME:
-            str = res->sa.s + res->treename ;
+        case E_RESOLVE_SERVICE_STATUS:
+            str = res->sa.s + res->path.status ;
+
+        // dependencies
+
+        case E_RESOLVE_SERVICE_DEPENDS:
+            str = res->sa.s + res->dependencies.depends ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REQUIREDBY:
+            str = res->sa.s + res->dependencies.requiredby ;
             break ;
 
-        case SERVICE_ENUM_STATE:
-            str = res->sa.s + res->state ;
+        case E_RESOLVE_SERVICE_OPTSDEPS:
+            str = res->sa.s + res->dependencies.optsdeps ;
             break ;
 
-        case SERVICE_ENUM_EXEC_RUN:
-            str = res->sa.s + res->exec_run ;
+        case E_RESOLVE_SERVICE_NDEPENDS:
+            fmt[uint32_fmt(fmt,res->dependencies.ndepends)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_EXEC_LOG_RUN:
-            str = res->sa.s + res->exec_log_run ;
+        case E_RESOLVE_SERVICE_NREQUIREDBY:
+            fmt[uint32_fmt(fmt,res->dependencies.nrequiredby)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_RUN:
-            str = res->sa.s + res->real_exec_run ;
+        case E_RESOLVE_SERVICE_NOPTSDEPS:
+            fmt[uint32_fmt(fmt,res->dependencies.noptsdeps)] = 0 ;
+            str = fmt ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_LOG_RUN:
-            str = res->sa.s + res->real_exec_log_run ;
+        // execute
+
+        case E_RESOLVE_SERVICE_RUN:
+            str = res->sa.s + res->execute.run.run ;
             break ;
 
-        case SERVICE_ENUM_EXEC_FINISH:
-            str = res->sa.s + res->exec_finish ;
+        case E_RESOLVE_SERVICE_RUN_USER:
+            str = res->sa.s + res->execute.run.run_user ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_FINISH:
-            str = res->sa.s + res->real_exec_finish ;
+        case E_RESOLVE_SERVICE_RUN_BUILD:
+            str = res->sa.s + res->execute.run.build ;
             break ;
 
-        case SERVICE_ENUM_TYPE:
-            fmt[uint32_fmt(fmt,res->type)] = 0 ;
+        case E_RESOLVE_SERVICE_RUN_SHEBANG:
+            str = res->sa.s + res->execute.run.shebang ;
+            break ;
+
+        case E_RESOLVE_SERVICE_RUN_RUNAS:
+            str = res->sa.s + res->execute.run.runas ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FINISH:
+            str = res->sa.s + res->execute.finish.run ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FINISH_USER:
+            str = res->sa.s + res->execute.finish.run_user ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FINISH_BUILD:
+            str = res->sa.s + res->execute.finish.build ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FINISH_SHEBANG:
+            str = res->sa.s + res->execute.finish.shebang ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FINISH_RUNAS:
+            str = res->sa.s + res->execute.finish.runas ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTKILL:
+            fmt[uint32_fmt(fmt,res->execute.timeout.kill)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTFINISH:
+            fmt[uint32_fmt(fmt,res->execute.timeout.finish)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTUP:
+            fmt[uint32_fmt(fmt,res->execute.timeout.up)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTDOWN:
+            fmt[uint32_fmt(fmt,res->execute.timeout.down)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_DOWN:
+            fmt[uint32_fmt(fmt,res->execute.down)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_DOWNSIGNAL:
+            fmt[uint32_fmt(fmt,res->execute.downsignal)] = 0 ;
+            str = fmt ;
+            break ;
+
+        // live
+
+        case E_RESOLVE_SERVICE_LIVEDIR:
+            str = res->sa.s + res->live.livedir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SCANDIR:
+            str = res->sa.s + res->live.scandir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_STATEDIR:
+            str = res->sa.s + res->live.statedir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_EVENTDIR:
+            str = res->sa.s + res->live.eventdir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_NOTIFDIR:
+            str = res->sa.s + res->live.notifdir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SUPERVISEDIR:
+            str = res->sa.s + res->live.supervisedir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FDHOLDERDIR:
+            str = res->sa.s + res->live.fdholderdir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ONESHOTDDIR:
+            str = res->sa.s + res->live.oneshotddir ;
+            break ;
+
+        // logger
+
+        case E_RESOLVE_SERVICE_LOGNAME:
+            str = res->sa.s + res->logger.name ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGDESTINATION:
+            str = res->sa.s + res->logger.destination ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGBACKUP:
+            fmt[uint32_fmt(fmt,res->logger.backup)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGMAXSIZE:
+            fmt[uint32_fmt(fmt,res->logger.maxsize)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGTIMESTAMP:
+            fmt[uint32_fmt(fmt,res->logger.timestamp)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_NDEPENDS:
-            fmt[uint32_fmt(fmt,res->ndepends)] = 0 ;
+        case E_RESOLVE_SERVICE_LOGWANT:
+            fmt[uint32_fmt(fmt,res->logger.want)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_NREQUIREDBY:
-            fmt[uint32_fmt(fmt,res->nrequiredby)] = 0 ;
+        case E_RESOLVE_SERVICE_LOGRUN:
+            str = res->sa.s + res->logger.execute.run.run ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_USER:
+            str = res->sa.s + res->logger.execute.run.run_user ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_BUILD:
+            str = res->sa.s + res->logger.execute.run.build ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_SHEBANG:
+            str = res->sa.s + res->logger.execute.run.shebang ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_RUNAS:
+            str = res->sa.s + res->logger.execute.run.runas ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGTIMEOUTKILL:
+            fmt[uint32_fmt(fmt,res->logger.timeout.kill)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_NOPTSDEPS:
-            fmt[uint32_fmt(fmt,res->noptsdeps)] = 0 ;
+        case E_RESOLVE_SERVICE_LOGTIMEOUTFINISH:
+            fmt[uint32_fmt(fmt,res->logger.timeout.finish)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_NEXTDEPS:
-            fmt[uint32_fmt(fmt,res->nextdeps)] = 0 ;
+
+        // environment
+
+        case E_RESOLVE_SERVICE_ENV:
+            str = res->sa.s + res->environ.env ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ENVDIR:
+            str = res->sa.s + res->environ.envdir ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ENV_OVERWRITE:
+            fmt[uint32_fmt(fmt,res->environ.env_overwrite)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_NCONTENTS:
-            fmt[uint32_fmt(fmt,res->ncontents)] = 0 ;
+        // regex
+
+        case E_RESOLVE_SERVICE_REGEX_CONFIGURE:
+            str = res->sa.s + res->regex.directories ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_DIRECTORIES:
+            str = res->sa.s + res->regex.directories ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_FILES:
+            str = res->sa.s + res->regex.files ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_INFILES:
+            str = res->sa.s + res->regex.infiles ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_NDIRECTORIES:
+            fmt[uint32_fmt(fmt,res->regex.ndirectories)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_DOWN:
-            fmt[uint32_fmt(fmt,res->down)] = 0 ;
+        case E_RESOLVE_SERVICE_REGEX_NFILES:
+            fmt[uint32_fmt(fmt,res->regex.nfiles)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_DISEN:
-            fmt[uint32_fmt(fmt,res->disen)] = 0 ;
+        case E_RESOLVE_SERVICE_REGEX_NINFILES:
+            fmt[uint32_fmt(fmt,res->regex.ninfiles)] = 0 ;
             str = fmt ;
             break ;
 
         default:
-            return 0 ;
+            return e ;
     }
 
     if (!auto_stra(sa,str))
-        return 0 ;
+        return e ;
 
-    return 1 ;
+    e = 1 ;
+    return e ;
 }
diff --git a/src/lib66/service/service_resolve_master_copy.c b/src/lib66/service/service_resolve_master_copy.c
index b305ce82..96791329 100644
--- a/src/lib66/service/service_resolve_master_copy.c
+++ b/src/lib66/service/service_resolve_master_copy.c
@@ -36,15 +36,19 @@ int service_resolve_master_copy(resolve_service_master_t *dst, resolve_service_m
     dst->name = mres->name ;
     dst->classic = mres->classic ;
     dst->bundle = mres->bundle ;
-    dst->longrun = mres->longrun ;
     dst->oneshot = mres->oneshot ;
     dst->module = mres->module ;
+    dst->enabled = mres->enabled ;
+    dst->disabled = mres->disabled ;
+    dst->contents = mres->contents ;
 
     dst->nclassic = mres->nclassic ;
     dst->nbundle = mres->nbundle ;
-    dst->nlongrun = mres->nlongrun ;
     dst->noneshot = mres->noneshot ;
     dst->nmodule = mres->nmodule ;
+    dst->nenabled = mres->nenabled ;
+    dst->ndisabled = mres->ndisabled ;
+    dst->ncontents = mres->ncontents ;
 
     return 1 ;
 
diff --git a/src/lib66/service/service_resolve_master_get_field_tosa.c b/src/lib66/service/service_resolve_master_get_field_tosa.c
index 0c1f3093..bec58c17 100644
--- a/src/lib66/service/service_resolve_master_get_field_tosa.c
+++ b/src/lib66/service/service_resolve_master_get_field_tosa.c
@@ -29,52 +29,70 @@ int service_resolve_master_get_field_tosa(stralloc *sa, resolve_service_master_t
 
     switch(field) {
 
-        case SERVICE_ENUM_MASTER_NAME:
+        case E_RESOLVE_SERVICE_MASTER_NAME:
             str = mres->sa.s + mres->name ;
             break ;
 
-        case SERVICE_ENUM_MASTER_CLASSIC:
+        case E_RESOLVE_SERVICE_MASTER_CLASSIC:
             str = mres->sa.s + mres->classic ;
             break ;
 
-        case SERVICE_ENUM_MASTER_LONGRUN:
-            str = mres->sa.s + mres->longrun ;
-            break ;
-
-        case SERVICE_ENUM_MASTER_BUNDLE:
+        case E_RESOLVE_SERVICE_MASTER_BUNDLE:
             str = mres->sa.s + mres->bundle ;
             break ;
 
-        case SERVICE_ENUM_MASTER_ONESHOT:
+        case E_RESOLVE_SERVICE_MASTER_ONESHOT:
             str = mres->sa.s + mres->oneshot ;
             break ;
 
-        case SERVICE_ENUM_MASTER_MODULE:
+        case E_RESOLVE_SERVICE_MASTER_MODULE:
             str = mres->sa.s + mres->module ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NCLASSIC:
+        case E_RESOLVE_SERVICE_MASTER_ENABLED:
+            str = mres->sa.s + mres->enabled ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_DISABLED:
+            str = mres->sa.s + mres->disabled ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_CONTENTS:
+            str = mres->sa.s + mres->contents ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NCLASSIC:
             fmt[uint32_fmt(fmt,mres->nclassic)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NBUNDLE:
+        case E_RESOLVE_SERVICE_MASTER_NBUNDLE:
             fmt[uint32_fmt(fmt,mres->nbundle)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NLONGRUN:
-            fmt[uint32_fmt(fmt,mres->nlongrun)] = 0 ;
+        case E_RESOLVE_SERVICE_MASTER_NONESHOT:
+            fmt[uint32_fmt(fmt,mres->noneshot)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NMODULE:
+            fmt[uint32_fmt(fmt,mres->nmodule)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NONESHOT:
-            fmt[uint32_fmt(fmt,mres->noneshot)] = 0 ;
+        case E_RESOLVE_SERVICE_MASTER_NENABLED:
+            fmt[uint32_fmt(fmt,mres->nenabled)] = 0 ;
             str = fmt ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NMODULE:
-            fmt[uint32_fmt(fmt,mres->nmodule)] = 0 ;
+        case E_RESOLVE_SERVICE_MASTER_NDISABLED:
+            fmt[uint32_fmt(fmt,mres->ndisabled)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NCONTENTS:
+            fmt[uint32_fmt(fmt,mres->ncontents)] = 0 ;
             str = fmt ;
             break ;
 
diff --git a/src/lib66/service/service_resolve_master_modify_field.c b/src/lib66/service/service_resolve_master_modify_field.c
index 591c40bf..9a39d827 100644
--- a/src/lib66/service/service_resolve_master_modify_field.c
+++ b/src/lib66/service/service_resolve_master_modify_field.c
@@ -26,19 +26,23 @@
 
 resolve_field_table_t resolve_service_master_field_table[] = {
 
-    [SERVICE_ENUM_MASTER_NAME] = { .field = "name" },
-    [SERVICE_ENUM_MASTER_CLASSIC] = { .field = "classic" },
-    [SERVICE_ENUM_MASTER_BUNDLE] = { .field = "bundle" },
-    [SERVICE_ENUM_MASTER_LONGRUN] = { .field = "longrun" },
-    [SERVICE_ENUM_MASTER_ONESHOT] = { .field = "oneshot" },
-    [SERVICE_ENUM_MASTER_MODULE] = { .field = "module" },
-
-    [SERVICE_ENUM_MASTER_NCLASSIC] = { .field = "nclassic" },
-    [SERVICE_ENUM_MASTER_NBUNDLE] = { .field = "nbundle" },
-    [SERVICE_ENUM_MASTER_NLONGRUN] = { .field = "nlongrun" },
-    [SERVICE_ENUM_MASTER_NONESHOT] = { .field = "noneshot" },
-    [SERVICE_ENUM_MASTER_NMODULE] = { .field = "nmodule" },
-    [SERVICE_ENUM_MASTER_ENDOFKEY] = { .field = 0 },
+    [E_RESOLVE_SERVICE_MASTER_NAME] = { .field = "name" },
+    [E_RESOLVE_SERVICE_MASTER_CLASSIC] = { .field = "classic" },
+    [E_RESOLVE_SERVICE_MASTER_BUNDLE] = { .field = "bundle" },
+    [E_RESOLVE_SERVICE_MASTER_ONESHOT] = { .field = "oneshot" },
+    [E_RESOLVE_SERVICE_MASTER_MODULE] = { .field = "module" },
+    [E_RESOLVE_SERVICE_MASTER_ENABLED] = { .field = "enabled" },
+    [E_RESOLVE_SERVICE_MASTER_DISABLED] = { .field = "disabled" },
+    [E_RESOLVE_SERVICE_MASTER_CONTENTS] = { .field = "contents" },
+
+    [E_RESOLVE_SERVICE_MASTER_NCLASSIC] = { .field = "nclassic" },
+    [E_RESOLVE_SERVICE_MASTER_NBUNDLE] = { .field = "nbundle" },
+    [E_RESOLVE_SERVICE_MASTER_NONESHOT] = { .field = "noneshot" },
+    [E_RESOLVE_SERVICE_MASTER_NMODULE] = { .field = "nmodule" },
+    [E_RESOLVE_SERVICE_MASTER_NENABLED] = { .field = "nenabled" },
+    [E_RESOLVE_SERVICE_MASTER_NDISABLED] = { .field = "ndisabled" },
+    [E_RESOLVE_SERVICE_MASTER_NCONTENTS] = { .field = "ncontents" },
+    [E_RESOLVE_SERVICE_MASTER_ENDOFKEY] = { .field = 0 },
 } ;
 
 int service_resolve_master_modify_field(resolve_service_master_t *mres, uint8_t field, char const *data)
@@ -52,53 +56,85 @@ int service_resolve_master_modify_field(resolve_service_master_t *mres, uint8_t
 
     switch(field) {
 
-        case SERVICE_ENUM_MASTER_NAME:
+        case E_RESOLVE_SERVICE_MASTER_NAME:
             mres->name = resolve_add_string(wres,data) ;
             break ;
 
-        case SERVICE_ENUM_MASTER_CLASSIC:
+        case E_RESOLVE_SERVICE_MASTER_CLASSIC:
             mres->classic = resolve_add_string(wres,data) ;
             break ;
 
-        case SERVICE_ENUM_MASTER_BUNDLE:
+        case E_RESOLVE_SERVICE_MASTER_BUNDLE:
             mres->bundle = resolve_add_string(wres,data) ;
             break ;
 
-        case SERVICE_ENUM_MASTER_LONGRUN:
-            mres->longrun = resolve_add_string(wres,data) ;
-            break ;
-
-        case SERVICE_ENUM_MASTER_ONESHOT:
+        case E_RESOLVE_SERVICE_MASTER_ONESHOT:
             mres->oneshot = resolve_add_string(wres,data) ;
             break ;
 
-        case SERVICE_ENUM_MASTER_MODULE:
+        case E_RESOLVE_SERVICE_MASTER_MODULE:
             mres->module = resolve_add_string(wres,data) ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NCLASSIC:
+        case E_RESOLVE_SERVICE_MASTER_ENABLED:
+            mres->enabled = resolve_add_string(wres,data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_DISABLED:
+            mres->disabled = resolve_add_string(wres,data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_CONTENTS:
+            mres->contents = resolve_add_string(wres,data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NCLASSIC:
+            if (!data)
+                data = "0" ;
             if (!uint0_scan(data, &ifield)) goto err ;
             mres->nclassic= ifield ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NBUNDLE:
+        case E_RESOLVE_SERVICE_MASTER_NBUNDLE:
+            if (!data)
+                data = "0" ;
             if (!uint0_scan(data, &ifield)) goto err ;
             mres->nbundle = ifield ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NLONGRUN:
+        case E_RESOLVE_SERVICE_MASTER_NONESHOT:
+            if (!data)
+                data = "0" ;
+            if (!uint0_scan(data, &ifield)) goto err ;
+            mres->noneshot = ifield ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NMODULE:
+            if (!data)
+                data = "0" ;
             if (!uint0_scan(data, &ifield)) goto err ;
-            mres->nlongrun = ifield ;
+            mres->nmodule = ifield ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NONESHOT:
+        case E_RESOLVE_SERVICE_MASTER_NENABLED:
+            if (!data)
+                data = "0" ;
             if (!uint0_scan(data, &ifield)) goto err ;
-            mres->noneshot = ifield ;
+            mres->nenabled = ifield ;
             break ;
 
-        case SERVICE_ENUM_MASTER_NMODULE:
+        case E_RESOLVE_SERVICE_MASTER_NDISABLED:
+            if (!data)
+                data = "0" ;
             if (!uint0_scan(data, &ifield)) goto err ;
-            mres->nmodule = ifield ;
+            mres->ndisabled = ifield ;
+            break ;
+
+        case E_RESOLVE_SERVICE_MASTER_NCONTENTS:
+            if (!data)
+                data = "0" ;
+            if (!uint0_scan(data, &ifield)) goto err ;
+            mres->ncontents = ifield ;
             break ;
 
         default:
diff --git a/src/lib66/service/service_resolve_master_read_cdb.c b/src/lib66/service/service_resolve_master_read_cdb.c
index 0e86fa91..23447075 100644
--- a/src/lib66/service/service_resolve_master_read_cdb.c
+++ b/src/lib66/service/service_resolve_master_read_cdb.c
@@ -47,10 +47,6 @@ int service_resolve_master_read_cdb(cdb *c, resolve_service_master_t *tres)
     resolve_find_cdb(&tmp,c,"bundle") ;
     tres->bundle = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
 
-    /* longrun */
-    resolve_find_cdb(&tmp,c,"longrun") ;
-    tres->longrun = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
     /* oneshot */
     resolve_find_cdb(&tmp,c,"oneshot") ;
     tres->oneshot = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
@@ -59,6 +55,18 @@ int service_resolve_master_read_cdb(cdb *c, resolve_service_master_t *tres)
     resolve_find_cdb(&tmp,c,"module") ;
     tres->module = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
 
+    /* enabled */
+    resolve_find_cdb(&tmp,c,"enabled") ;
+    tres->enabled = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* disabled */
+    resolve_find_cdb(&tmp,c,"disabled") ;
+    tres->disabled = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* contents */
+    resolve_find_cdb(&tmp,c,"contents") ;
+    tres->contents = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
     /* nclassic */
     x = resolve_find_cdb(&tmp,c,"nclassic") ;
     tres->nclassic = x ;
@@ -67,10 +75,6 @@ int service_resolve_master_read_cdb(cdb *c, resolve_service_master_t *tres)
     x = resolve_find_cdb(&tmp,c,"nbundle") ;
     tres->nbundle = x ;
 
-    /* nlongrun */
-    x = resolve_find_cdb(&tmp,c,"nlongrun") ;
-    tres->nlongrun = x ;
-
     /* noneshot */
     x = resolve_find_cdb(&tmp,c,"noneshot") ;
     tres->noneshot = x ;
@@ -79,6 +83,18 @@ int service_resolve_master_read_cdb(cdb *c, resolve_service_master_t *tres)
     x = resolve_find_cdb(&tmp,c,"nmodule") ;
     tres->nmodule = x ;
 
+    /* nenabled */
+    x = resolve_find_cdb(&tmp,c,"nenabled") ;
+    tres->nenabled = x ;
+
+    /* ndisabled */
+    x = resolve_find_cdb(&tmp,c,"ndisabled") ;
+    tres->ndisabled = x ;
+
+    /* ncontents */
+    x = resolve_find_cdb(&tmp,c,"ncontents") ;
+    tres->ncontents = x ;
+
     free(wres) ;
     stralloc_free(&tmp) ;
 
diff --git a/src/lib66/service/service_resolve_master_write.c b/src/lib66/service/service_resolve_master_write.c
index 1addc665..4aaa5f9f 100644
--- a/src/lib66/service/service_resolve_master_write.c
+++ b/src/lib66/service/service_resolve_master_write.c
@@ -16,12 +16,15 @@
 
 #include <oblibs/log.h>
 #include <oblibs/string.h>
+#include <oblibs/types.h>
 
 #include <skalibs/genalloc.h>
 
 #include <66/constants.h>
 #include <66/resolve.h>
 #include <66/graph.h>
+#include <66/enum.h>
+#include <66/state.h>
 #include <66/service.h>
 
 int service_resolve_master_write(graph_t *graph, char const *dest)
@@ -31,6 +34,7 @@ int service_resolve_master_write(graph_t *graph, char const *dest)
     int e = 0 ;
     unsigned int pos = 0 ;
 
+    ss_state_t ste = STATE_ZERO ;
     resolve_service_master_t mres = RESOLVE_SERVICE_MASTER_ZERO ;
     resolve_wrapper_t_ref mwres = resolve_set_struct(DATA_SERVICE_MASTER, &mres) ;
 
@@ -39,54 +43,67 @@ int service_resolve_master_write(graph_t *graph, char const *dest)
 
     resolve_init(mwres) ;
 
-    {
-        for (; pos < graph->sort_count ; pos++) {
 
-           char *name = graph->data.s + genalloc_s(graph_hash_t,&graph->hash)[graph->sort[pos]].vertex ;
+    for (; pos < graph->sort_count ; pos++) {
 
-            if (resolve_read_g(wres, dest, name) <= 0) {
-                log_warnu("read resolve file of: ", dest, name) ;
-                goto err ;
-            }
+        char *name = graph->data.s + genalloc_s(graph_hash_t,&graph->hash)[graph->sort[pos]].vertex ;
+
+        if (!resolve_check(dest, name) ||
+            !resolve_read(wres, dest, name)) {
+            log_warnu("read resolve file of: ", dest, name) ;
+            goto err ;
+        }
 
-            switch (res.type) {
+        switch (res.type) {
 
-                case TYPE_CLASSIC:
+            case TYPE_CLASSIC:
 
-                    mres.classic = resolve_add_string(mwres, res.sa.s + res.name) ;
-                    mres.nclassic++ ;
-                    break ;
+                mres.classic = resolve_add_string(mwres, name) ;
+                mres.nclassic++ ;
+                break ;
 
-                case TYPE_BUNDLE:
+            case TYPE_BUNDLE:
 
-                    mres.bundle = resolve_add_string(mwres, res.sa.s + res.name) ;
-                    mres.nbundle++ ;
-                    break ;
+                mres.bundle = resolve_add_string(mwres, name) ;
+                mres.nbundle++ ;
+                break ;
 
-                case TYPE_LONGRUN:
+            case TYPE_ONESHOT:
 
-                    mres.longrun = resolve_add_string(mwres, res.sa.s + res.name) ;
-                    mres.nlongrun++ ;
-                    break ;
+                mres.oneshot = resolve_add_string(mwres, name) ;
+                mres.noneshot++ ;
+                break ;
 
+            case TYPE_MODULE:
 
-                case TYPE_ONESHOT:
+                mres.module = resolve_add_string(mwres, name) ;
+                mres.nmodule++ ;
+                break ;
 
-                    mres.oneshot = resolve_add_string(mwres, res.sa.s + res.name) ;
-                    mres.noneshot++ ;
-                    break ;
+            default:
+                log_warn("unknown type") ;
+                goto err ;
+        }
 
-                case TYPE_MODULE:
+        if (!state_read(&ste, res.sa.s + res.path.home, name))
+            log_warnu("read state file of: ", name) ;
 
-                    mres.module = resolve_add_string(mwres, res.sa.s + res.name) ;
-                    mres.nmodule++ ;
-                    break ;
 
-                default:
-                    log_warn("unknown type") ;
-                    goto err ;
-            }
+        if (!FLAGS_ISSET(ste.isenabled, STATE_FLAGS_TRUE)) {
+
+            /* disabled */
+            mres.disabled = resolve_add_string(mwres, res.sa.s + res.name) ;
+            mres.ndisabled++ ;
+
+        } else {
+            /* enabled */
+
+            mres.enabled = resolve_add_string(mwres, res.sa.s + res.name) ;
+            mres.nenabled++ ;
         }
+
+        mres.contents = resolve_add_string(mwres, res.sa.s + res.name) ;
+        mres.ncontents++ ;
     }
 
     if (!resolve_write(mwres, dest, SS_MASTER + 1))
diff --git a/src/lib66/service/service_resolve_master_write_cdb.c b/src/lib66/service/service_resolve_master_write_cdb.c
index 4b84bf2a..4f8a0cf2 100644
--- a/src/lib66/service/service_resolve_master_write_cdb.c
+++ b/src/lib66/service/service_resolve_master_write_cdb.c
@@ -34,29 +34,41 @@ int service_resolve_master_write_cdb(cdbmaker *c, resolve_service_master_t *mres
     /* bundle */
     !resolve_add_cdb(c,"bundle",str + mres->bundle) ||
 
-    /* longrun */
-    !resolve_add_cdb(c,"longrun",str + mres->longrun) ||
-
     /* oneshot */
     !resolve_add_cdb(c,"oneshot",str + mres->oneshot) ||
 
     /* module */
     !resolve_add_cdb(c,"module",str + mres->module) ||
 
+    /* enabled */
+    !resolve_add_cdb(c,"enabled",str + mres->enabled) ||
+
+    /* disabled */
+    !resolve_add_cdb(c,"disabled",str + mres->disabled) ||
+
+    /* contents */
+    !resolve_add_cdb(c,"contents",str + mres->contents) ||
+
     /* nclassic */
     !resolve_add_cdb_uint(c,"nclassic",mres->nclassic) ||
 
     /* nbundle */
     !resolve_add_cdb_uint(c,"nbundle",mres->nbundle) ||
 
-    /* nlongrun */
-    !resolve_add_cdb_uint(c,"nlongrun",mres->nlongrun) ||
-
     /* noneshot */
     !resolve_add_cdb_uint(c,"noneshot",mres->noneshot) ||
 
     /* nmodule */
-    !resolve_add_cdb_uint(c,"nmodule",mres->nmodule)) return 0 ;
+    !resolve_add_cdb_uint(c,"nmodule",mres->nmodule) ||
+
+    /* nenabled */
+    !resolve_add_cdb_uint(c,"nenabled",mres->nenabled) ||
+
+    /* ndisabled */
+    !resolve_add_cdb_uint(c,"ndisabled",mres->ndisabled) ||
+
+    /* ncontents */
+    !resolve_add_cdb_uint(c,"ncontents",mres->ncontents)) return 0 ;
 
     return 1 ;
 }
diff --git a/src/lib66/service/service_resolve_modify_field.c b/src/lib66/service/service_resolve_modify_field.c
index 8c41afdf..3ce7e42b 100644
--- a/src/lib66/service/service_resolve_modify_field.c
+++ b/src/lib66/service/service_resolve_modify_field.c
@@ -22,201 +22,422 @@
 
 resolve_field_table_t resolve_service_field_table[] = {
 
-    [SERVICE_ENUM_NAME] = { .field = "name" },
-    [SERVICE_ENUM_DESCRIPTION] = { .field = "description" },
-    [SERVICE_ENUM_VERSION] = { .field = "version" },
-    [SERVICE_ENUM_LOGGER] = { .field = "logger" },
-    [SERVICE_ENUM_LOGREAL] = { .field = "logreal" },
-    [SERVICE_ENUM_LOGASSOC] = { .field = "logassoc" },
-    [SERVICE_ENUM_DSTLOG] = { .field = "dstlog" },
-    [SERVICE_ENUM_DEPENDS] = { .field = "depends" },
-    [SERVICE_ENUM_REQUIREDBY] = { .field = "requiredby" },
-    [SERVICE_ENUM_OPTSDEPS] = { .field = "optsdeps" },
-    [SERVICE_ENUM_EXTDEPS] = { .field = "extdeps" },
-    [SERVICE_ENUM_CONTENTS] = { .field = "contents" },
-    [SERVICE_ENUM_SRC] = { .field = "src" },
-    [SERVICE_ENUM_SRCONF] = { .field = "srconf" },
-    [SERVICE_ENUM_LIVE] = { .field = "live" },
-    [SERVICE_ENUM_RUNAT] = { .field = "runat" },
-    [SERVICE_ENUM_TREE] = { .field = "tree" },
-    [SERVICE_ENUM_TREENAME] = { .field = "treename" },
-    [SERVICE_ENUM_STATE] = { .field = "state" },
-    [SERVICE_ENUM_EXEC_RUN] = { .field = "exec_run" },
-    [SERVICE_ENUM_EXEC_LOG_RUN] = { .field = "exec_log_run" },
-    [SERVICE_ENUM_REAL_EXEC_RUN] = { .field = "real_exec_run" },
-    [SERVICE_ENUM_REAL_EXEC_LOG_RUN] = { .field = "real_exec_log_run" },
-    [SERVICE_ENUM_EXEC_FINISH] = { .field = "exec_finish" },
-    [SERVICE_ENUM_REAL_EXEC_FINISH] = { .field = "real_exec_finish" },
-    [SERVICE_ENUM_TYPE] = { .field = "type" },
-    [SERVICE_ENUM_NDEPENDS] = { .field = "ndepends" },
-    [SERVICE_ENUM_NREQUIREDBY] = { .field = "nrequiredby" },
-    [SERVICE_ENUM_NOPTSDEPS] = { .field = "noptsdeps" },
-    [SERVICE_ENUM_NEXTDEPS] = { .field = "nextdeps" },
-    [SERVICE_ENUM_NCONTENTS] = { .field = "ncontents" },
-    [SERVICE_ENUM_DOWN] = { .field = "down" },
-    [SERVICE_ENUM_DISEN] = { .field = "disen" },
-    [SERVICE_ENUM_ENDOFKEY] = { .field = 0 }
+    [E_RESOLVE_SERVICE_NAME] = { .field = "name" },
+    [E_RESOLVE_SERVICE_DESCRIPTION] = { .field = "description" },
+    [E_RESOLVE_SERVICE_VERSION] = { .field = "version" },
+    [E_RESOLVE_SERVICE_TYPE] = { .field = "type" },
+    [E_RESOLVE_SERVICE_NOTIFY] = { .field = "notify" },
+    [E_RESOLVE_SERVICE_MAXDEATH] = { .field = "maxdeath" },
+    [E_RESOLVE_SERVICE_EARLIER] = { .field = "earlier" },
+    [E_RESOLVE_SERVICE_HIERCOPY] = { .field = "hiercopy" },
+    [E_RESOLVE_SERVICE_INTREE] = { .field = "intree" },
+    [E_RESOLVE_SERVICE_OWNERSTR] = { .field = "ownerstr" },
+    [E_RESOLVE_SERVICE_OWNER] = { .field = "owner" },
+    [E_RESOLVE_SERVICE_TREENAME] = { .field = "treename" },
+    [E_RESOLVE_SERVICE_USER] = { .field = "user" },
+    [E_RESOLVE_SERVICE_INMODULE] = { .field = "inmodule" },
+
+    // path
+    [E_RESOLVE_SERVICE_HOME] = { .field = "home" },
+    [E_RESOLVE_SERVICE_FRONTEND] = { .field = "frontend" },
+    [E_RESOLVE_SERVICE_TREE] = { .field = "tree" },
+    [E_RESOLVE_SERVICE_STATUS] = { .field = "status" },
+
+    // dependencies
+    [E_RESOLVE_SERVICE_DEPENDS] = { .field = "depends" },
+    [E_RESOLVE_SERVICE_REQUIREDBY] = { .field = "requiredby" },
+    [E_RESOLVE_SERVICE_OPTSDEPS] = { .field = "optsdeps" },
+    [E_RESOLVE_SERVICE_NDEPENDS] = { .field = "ndepends" },
+    [E_RESOLVE_SERVICE_NREQUIREDBY] = { .field = "nrequiredby" },
+    [E_RESOLVE_SERVICE_NOPTSDEPS] = { .field = "noptsdeps" },
+
+    // execute
+    [E_RESOLVE_SERVICE_RUN] = { .field = "run" },
+    [E_RESOLVE_SERVICE_RUN_USER] = { .field = "run_user" },
+    [E_RESOLVE_SERVICE_RUN_BUILD] = { .field = "run_build" },
+    [E_RESOLVE_SERVICE_RUN_SHEBANG] = { .field = "run_shebang" },
+    [E_RESOLVE_SERVICE_RUN_RUNAS] = { .field = "run_runas" },
+    [E_RESOLVE_SERVICE_FINISH] = { .field = "finish" },
+    [E_RESOLVE_SERVICE_FINISH_USER] = { .field = "finish_user" },
+    [E_RESOLVE_SERVICE_FINISH_BUILD] = { .field = "finish_build" },
+    [E_RESOLVE_SERVICE_FINISH_SHEBANG] = { .field = "finish_shebang" },
+    [E_RESOLVE_SERVICE_FINISH_RUNAS] = { .field = "finish_runas" },
+    [E_RESOLVE_SERVICE_TIMEOUTKILL] = { .field = "timeoutkill" },
+    [E_RESOLVE_SERVICE_TIMEOUTFINISH] = { .field = "timeoutfinish" },
+    [E_RESOLVE_SERVICE_TIMEOUTUP] = { .field = "timeoutup" },
+    [E_RESOLVE_SERVICE_TIMEOUTDOWN] = { .field = "timeoutdown" },
+    [E_RESOLVE_SERVICE_DOWN] = { .field = "down" },
+    [E_RESOLVE_SERVICE_DOWNSIGNAL] = { .field = "downsignal" },
+
+    // live
+    [E_RESOLVE_SERVICE_LIVEDIR] = { .field = "livedir" },
+    [E_RESOLVE_SERVICE_SCANDIR] = { .field = "scandirdir" },
+    [E_RESOLVE_SERVICE_STATEDIR] = { .field = "statedir" },
+    [E_RESOLVE_SERVICE_EVENTDIR] = { .field = "eventdir" },
+    [E_RESOLVE_SERVICE_NOTIFDIR] = { .field = "notifdir" },
+    [E_RESOLVE_SERVICE_SUPERVISEDIR] = { .field = "supervisedir" },
+    [E_RESOLVE_SERVICE_FDHOLDERDIR] = { .field = "fdholderdir" },
+    [E_RESOLVE_SERVICE_ONESHOTDDIR] = { .field = "oneshotddir" },
+
+    // logger
+    [E_RESOLVE_SERVICE_LOGNAME] = { .field = "logname" },
+    [E_RESOLVE_SERVICE_LOGDESTINATION] = { .field = "logdestination" },
+    [E_RESOLVE_SERVICE_LOGBACKUP] = { .field = "logbackup" },
+    [E_RESOLVE_SERVICE_LOGMAXSIZE] = { .field = "logmaxsize" },
+    [E_RESOLVE_SERVICE_LOGTIMESTAMP] = { .field = "logtimestamp" },
+    [E_RESOLVE_SERVICE_LOGWANT] = { .field = "logwant" },
+    [E_RESOLVE_SERVICE_LOGRUN] = { .field = "logrun" },
+    [E_RESOLVE_SERVICE_LOGRUN_USER] = { .field = "logrun_user" },
+    [E_RESOLVE_SERVICE_LOGRUN_BUILD] = { .field = "logrun_build" },
+    [E_RESOLVE_SERVICE_LOGRUN_SHEBANG] = { .field = "logrun_shebang" },
+    [E_RESOLVE_SERVICE_LOGRUN_RUNAS] = { .field = "logrun_runas" },
+    [E_RESOLVE_SERVICE_LOGTIMEOUTKILL] = { .field = "logtimeoutkill" },
+    [E_RESOLVE_SERVICE_LOGTIMEOUTFINISH] = { .field = "logtimeoutfinish" },
+
+    // environment
+    [E_RESOLVE_SERVICE_ENV] = { .field = "env" },
+    [E_RESOLVE_SERVICE_ENVDIR] = { .field = "envdir" },
+    [E_RESOLVE_SERVICE_ENV_OVERWRITE] = { .field = "env_overwrite" },
+
+    // regex
+    [E_RESOLVE_SERVICE_REGEX_CONFIGURE] = { .field = "configure" },
+    [E_RESOLVE_SERVICE_REGEX_DIRECTORIES] = { .field = "directories" },
+    [E_RESOLVE_SERVICE_REGEX_FILES] = { .field = "files" },
+    [E_RESOLVE_SERVICE_REGEX_INFILES] = { .field = "infiles" },
+    [E_RESOLVE_SERVICE_REGEX_NDIRECTORIES] = { .field = "ndirectories" },
+    [E_RESOLVE_SERVICE_REGEX_NFILES] = { .field = "nfiles" },
+    [E_RESOLVE_SERVICE_REGEX_NINFILES] = { .field = "ninfiles" },
+    [E_RESOLVE_SERVICE_ENDOFKEY] = { .field = 0 }
 } ;
+uint32_t resolve_add_uint(char const *data)
+{
+    uint32_t u ;
+
+    if (!data)
+        data = "0" ;
+    if (!uint0_scan(data, &u))
+        return 0 ;
+    return u ;
+}
 
 int service_resolve_modify_field(resolve_service_t *res, resolve_service_enum_t field, char const *data)
 {
     log_flow() ;
 
-    uint32_t ifield ;
     int e = 0 ;
 
     resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ;
 
     switch(field) {
 
-        case SERVICE_ENUM_NAME:
-            res->name = resolve_add_string(wres,data) ;
+        // configuration
+
+        case E_RESOLVE_SERVICE_NAME:
+            res->name = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_DESCRIPTION:
+            res->description = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_DESCRIPTION:
-            res->description = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_VERSION:
+            res->version = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_VERSION:
-            res->version = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_TYPE:
+            res->type = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_LOGGER:
-            res->logger = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_NOTIFY:
+            res->notify = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_LOGREAL:
-            res->logreal = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_MAXDEATH:
+            res->maxdeath = resolve_add_uint(data) ; ;
             break ;
 
-        case SERVICE_ENUM_LOGASSOC:
-            res->logassoc = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_EARLIER:
+            res->earlier = resolve_add_uint(data) ; ;
             break ;
 
-        case SERVICE_ENUM_DSTLOG:
-            res->dstlog = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_HIERCOPY:
+            res->hiercopy = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_DEPENDS:
-            res->depends = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_INTREE:
+            res->intree = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_REQUIREDBY:
-            res->requiredby = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_OWNERSTR:
+            res->ownerstr = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_OPTSDEPS:
-            res->optsdeps = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_OWNER:
+            res->owner = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_EXTDEPS:
-            res->extdeps = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_TREENAME:
+            res->treename = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_CONTENTS:
-            res->contents = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_USER:
+            res->user = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_SRC:
-            res->src = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_INMODULE:
+            res->inmodule = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_SRCONF:
-            res->srconf = resolve_add_string(wres,data) ;
+        // path
+
+        case E_RESOLVE_SERVICE_HOME:
+            res->path.home = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_LIVE:
-            res->live = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_FRONTEND:
+            res->path.frontend = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_RUNAT:
-            res->runat = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_TREE:
+            res->path.tree = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_TREE:
-            res->tree = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_STATUS:
+            res->path.status = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_TREENAME:
-            res->treename = resolve_add_string(wres,data) ;
+        // dependencies
+
+        case E_RESOLVE_SERVICE_DEPENDS:
+            res->dependencies.depends = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_STATE:
-            res->state = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_REQUIREDBY:
+            res->dependencies.requiredby = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_EXEC_RUN:
-            res->exec_run = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_OPTSDEPS:
+            res->dependencies.optsdeps = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_EXEC_LOG_RUN:
-            res->exec_log_run = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_NDEPENDS:
+            res->dependencies.ndepends = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_RUN:
-            res->real_exec_run = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_NREQUIREDBY:
+            res->dependencies.nrequiredby = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_LOG_RUN:
-            res->real_exec_log_run = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_NOPTSDEPS:
+            res->dependencies.noptsdeps = resolve_add_uint(data) ;
             break ;
 
-        case SERVICE_ENUM_EXEC_FINISH:
-            res->exec_finish = resolve_add_string(wres,data) ;
+
+        // execute
+
+        case E_RESOLVE_SERVICE_RUN:
+            res->execute.run.run = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_REAL_EXEC_FINISH:
-            res->real_exec_finish = resolve_add_string(wres,data) ;
+        case E_RESOLVE_SERVICE_RUN_USER:
+            res->execute.run.run_user = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_TYPE:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->type = ifield ;
+        case E_RESOLVE_SERVICE_RUN_BUILD:
+            res->execute.run.build = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_NDEPENDS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->ndepends = ifield ;
+        case E_RESOLVE_SERVICE_RUN_SHEBANG:
+            res->execute.run.shebang = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_NREQUIREDBY:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->nrequiredby = ifield ;
+        case E_RESOLVE_SERVICE_RUN_RUNAS:
+            res->execute.run.runas = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_NOPTSDEPS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->noptsdeps = ifield ;
+        case E_RESOLVE_SERVICE_FINISH:
+            res->execute.finish.run = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_NEXTDEPS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->nextdeps = ifield ;
+        case E_RESOLVE_SERVICE_FINISH_USER:
+            res->execute.finish.run_user = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_NCONTENTS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->ncontents = ifield ;
+        case E_RESOLVE_SERVICE_FINISH_BUILD:
+            res->execute.finish.build = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_DOWN:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->down = ifield ;
+        case E_RESOLVE_SERVICE_FINISH_SHEBANG:
+            res->execute.finish.shebang = resolve_add_string(wres, data) ;
             break ;
 
-        case SERVICE_ENUM_DISEN:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            res->disen = ifield ;
+        case E_RESOLVE_SERVICE_FINISH_RUNAS:
+            res->execute.finish.runas = resolve_add_string(wres, data) ;
             break ;
 
-        default:
+        case E_RESOLVE_SERVICE_TIMEOUTKILL:
+            res->execute.timeout.kill = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTFINISH:
+            res->execute.timeout.finish = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTUP:
+            res->execute.timeout.up = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_TIMEOUTDOWN:
+            res->execute.timeout.down = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_DOWN:
+            res->execute.down = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_DOWNSIGNAL:
+            res->execute.downsignal = resolve_add_uint(data) ;
+            break ;
+
+        // live
+
+        case E_RESOLVE_SERVICE_LIVEDIR:
+            res->live.livedir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SCANDIR:
+            res->live.scandir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_STATEDIR:
+            res->live.statedir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_EVENTDIR:
+            res->live.eventdir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_NOTIFDIR:
+            res->live.notifdir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_SUPERVISEDIR:
+            res->live.supervisedir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_FDHOLDERDIR:
+            res->live.fdholderdir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ONESHOTDDIR:
+            res->live.oneshotddir = resolve_add_string(wres, data) ;
+            break ;
+
+        // logger
+
+        case E_RESOLVE_SERVICE_LOGNAME:
+            res->logger.name = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGDESTINATION:
+            res->logger.destination = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGBACKUP:
+            res->logger.backup = resolve_add_uint(data) ;
             break ;
+
+        case E_RESOLVE_SERVICE_LOGMAXSIZE:
+            res->logger.maxsize = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGTIMESTAMP:
+            res->logger.timestamp = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGWANT:
+            res->logger.want = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN:
+            res->logger.execute.run.run = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_USER:
+            res->logger.execute.run.run_user = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_BUILD:
+            res->logger.execute.run.build = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_SHEBANG:
+            res->logger.execute.run.shebang = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGRUN_RUNAS:
+            res->logger.execute.run.runas = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGTIMEOUTKILL:
+            res->logger.timeout.kill = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_LOGTIMEOUTFINISH:
+            res->logger.timeout.finish = resolve_add_uint(data) ;
+            break ;
+
+        // environment
+
+        case E_RESOLVE_SERVICE_ENV:
+            res->environ.env = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ENVDIR:
+            res->environ.envdir = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_ENV_OVERWRITE:
+            res->environ.env_overwrite = resolve_add_uint(data) ;
+            break ;
+
+        // regex
+
+        case E_RESOLVE_SERVICE_REGEX_CONFIGURE:
+            res->regex.configure = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_DIRECTORIES:
+            res->regex.directories = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_FILES:
+            res->regex.files = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_INFILES:
+            res->regex.infiles = resolve_add_string(wres, data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_NDIRECTORIES:
+            res->regex.ndirectories = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_NFILES:
+            res->regex.nfiles = resolve_add_uint(data) ;
+            break ;
+
+        case E_RESOLVE_SERVICE_REGEX_NINFILES:
+            res->regex.ninfiles = resolve_add_uint(data) ;
+            break ;
+
+        default:
+            return e ;
     }
 
     e = 1 ;
 
-    err:
-        free(wres) ;
-        return e ;
+   free(wres) ;
+   return e ;
 
 }
diff --git a/src/lib66/service/service_resolve_read_cdb.c b/src/lib66/service/service_resolve_read_cdb.c
index 2cbd9847..4d6fa15b 100644
--- a/src/lib66/service/service_resolve_read_cdb.c
+++ b/src/lib66/service/service_resolve_read_cdb.c
@@ -33,137 +33,164 @@ int service_resolve_read_cdb(cdb *c, resolve_service_t *res)
 
     wres = resolve_set_struct(DATA_SERVICE, res) ;
 
-    /* name */
+    /* configuration */
     resolve_find_cdb(&tmp,c,"name") ;
     res->name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* description */
     resolve_find_cdb(&tmp,c,"description") ;
     res->description = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* version */
     resolve_find_cdb(&tmp,c,"version") ;
     res->version = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"type") ;
+    res->type = x ;
+    x = resolve_find_cdb(&tmp,c,"notify") ;
+    res->notify = x ;
+    x = resolve_find_cdb(&tmp,c,"maxdeath") ;
+    res->maxdeath = x ;
+    x = resolve_find_cdb(&tmp,c,"earlier") ;
+    res->earlier = x ;
+    resolve_find_cdb(&tmp,c,"hiercopy") ;
+    res->hiercopy = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"intree") ;
+    res->intree = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"ownerstr") ;
+    res->ownerstr = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"owner") ;
+    res->owner = x ;
+    resolve_find_cdb(&tmp,c,"treename") ;
+    res->treename = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"user") ;
+    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 ;
+
+    /* 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,"tree") ;
+    res->path.tree = 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 ;
 
-    /* logger */
-    resolve_find_cdb(&tmp,c,"logger") ;
-    res->logger = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* logreal */
-    resolve_find_cdb(&tmp,c,"logreal") ;
-    res->logreal = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* logassoc */
-    resolve_find_cdb(&tmp,c,"logassoc") ;
-    res->logassoc = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* dstlog */
-    resolve_find_cdb(&tmp,c,"dstlog") ;
-    res->dstlog = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* depends */
+    /* dependencies */
     resolve_find_cdb(&tmp,c,"depends") ;
-    res->depends = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* requiredby */
+    res->dependencies.depends = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"requiredby") ;
-    res->requiredby = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* optsdeps */
+    res->dependencies.requiredby = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     resolve_find_cdb(&tmp,c,"optsdeps") ;
-    res->optsdeps = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* extdeps */
-    resolve_find_cdb(&tmp,c,"extdeps") ;
-    res->extdeps = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* contents */
-    resolve_find_cdb(&tmp,c,"contents") ;
-    res->contents = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* src */
-    resolve_find_cdb(&tmp,c,"src") ;
-    res->src = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* srconf */
-    resolve_find_cdb(&tmp,c,"srconf") ;
-    res->srconf = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* live */
-    resolve_find_cdb(&tmp,c,"live") ;
-    res->live = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* runat */
-    resolve_find_cdb(&tmp,c,"runat") ;
-    res->runat = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* tree */
-    resolve_find_cdb(&tmp,c,"tree") ;
-    res->tree = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* treename */
-    resolve_find_cdb(&tmp,c,"treename") ;
-    res->treename = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* state */
-    resolve_find_cdb(&tmp,c,"state") ;
-    res->state = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* exec_run */
-    resolve_find_cdb(&tmp,c,"exec_run") ;
-    res->exec_run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* exec_log_run */
-    resolve_find_cdb(&tmp,c,"exec_log_run") ;
-    res->exec_log_run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* real_exec_run */
-    resolve_find_cdb(&tmp,c,"real_exec_run") ;
-    res->real_exec_run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* real_exec_log_run */
-    resolve_find_cdb(&tmp,c,"real_exec_log_run") ;
-    res->real_exec_log_run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* exec_finish */
-    resolve_find_cdb(&tmp,c,"exec_finish") ;
-    res->exec_finish = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* real_exec_finish */
-    resolve_find_cdb(&tmp,c,"real_exec_finish") ;
-    res->real_exec_finish = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* type */
-    x = resolve_find_cdb(&tmp,c,"type") ;
-    res->type = x ;
-
-    /* ndepends */
+    res->dependencies.optsdeps = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
     x = resolve_find_cdb(&tmp,c,"ndepends") ;
-    res->ndepends = x ;
-
-    /* nrequiredby */
+    res->dependencies.ndepends = x ;
     x = resolve_find_cdb(&tmp,c,"nrequiredby") ;
-    res->nrequiredby = x ;
-
-    /* noptsdeps */
+    res->dependencies.nrequiredby = x ;
     x = resolve_find_cdb(&tmp,c,"noptsdeps") ;
-    res->noptsdeps = x ;
-
-    /* nextdeps */
-    x = resolve_find_cdb(&tmp,c,"nextdeps") ;
-    res->nextdeps = x ;
+    res->dependencies.noptsdeps = x ;
+
+    /* execute */
+    resolve_find_cdb(&tmp,c,"run") ;
+    res->execute.run.run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"run_user") ;
+    res->execute.run.run_user = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"run_build") ;
+    res->execute.run.build = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"run_shebang") ;
+    res->execute.run.shebang = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"run_runas") ;
+    res->execute.run.runas = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"finish") ;
+    res->execute.finish.run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"finish_user") ;
+    res->execute.finish.run_user = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"finish_build") ;
+    res->execute.finish.build = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"finish_shebang") ;
+    res->execute.finish.shebang = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"finish_runas") ;
+    res->execute.finish.runas = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"timeoutkill") ;
+    res->execute.timeout.kill = x ;
+    x = resolve_find_cdb(&tmp,c,"timeoutfinish") ;
+    res->execute.timeout.finish = x ;
+    x = resolve_find_cdb(&tmp,c,"timeoutup") ;
+    res->execute.timeout.up = x ;
+    x = resolve_find_cdb(&tmp,c,"timeoutdown") ;
+    res->execute.timeout.down = x ;
+    x = resolve_find_cdb(&tmp,c,"down") ;
+    res->execute.down = x ;
+    x = resolve_find_cdb(&tmp,c,"downsignal") ;
+    res->execute.downsignal = x ;
 
-    /* ncontents */
-    x = resolve_find_cdb(&tmp,c,"ncontents") ;
-    res->ncontents = x ;
+    /* live */
+    resolve_find_cdb(&tmp,c,"livedir") ;
+    res->live.livedir = 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") ;
+    res->live.statedir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"eventdir") ;
+    res->live.eventdir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"notifdir") ;
+    res->live.notifdir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"supervisedir") ;
+    res->live.supervisedir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"fdholderdir") ;
+    res->live.fdholderdir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"oneshotddir") ;
+    res->live.oneshotddir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
 
-    /* down */
-    x = resolve_find_cdb(&tmp,c,"down") ;
-    res->down = x ;
+    /* logger */
+    resolve_find_cdb(&tmp,c,"logname") ;
+    res->logger.name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"logdestination") ;
+    res->logger.destination = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"logbackup") ;
+    res->logger.backup = x ;
+    x = resolve_find_cdb(&tmp,c,"logmaxsize") ;
+    res->logger.maxsize = x ;
+    x = resolve_find_cdb(&tmp,c,"logtimestamp") ;
+    res->logger.timestamp = x ;
+    x = resolve_find_cdb(&tmp,c,"logwant") ;
+    res->logger.want = x ;
+    resolve_find_cdb(&tmp,c,"logrun") ;
+    res->logger.execute.run.run = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"logrun_user") ;
+    res->logger.execute.run.run_user = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"logrun_build") ;
+    res->logger.execute.run.build = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"logrun_shebang") ;
+    res->logger.execute.run.shebang = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"logrun_runas") ;
+    res->logger.execute.run.runas = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"logtimeoutkill") ;
+    res->logger.timeout.kill = x ;
+    x = resolve_find_cdb(&tmp,c,"logtimeoutfinish") ;
+    res->logger.timeout.finish = x ;
+
+    /* environment */
+    resolve_find_cdb(&tmp,c,"env") ;
+    res->environ.env = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"envdir") ;
+    res->environ.envdir = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"env_overwrite") ;
+    res->environ.env_overwrite = x ;
+
+    /* regex */
+    resolve_find_cdb(&tmp,c,"configure") ;
+    res->regex.configure = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"directories") ;
+    res->regex.directories = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"files") ;
+    res->regex.files = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    resolve_find_cdb(&tmp,c,"infiles") ;
+    res->regex.infiles = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+    x = resolve_find_cdb(&tmp,c,"ndirectories") ;
+    res->regex.ndirectories = x ;
+    x = resolve_find_cdb(&tmp,c,"nfiles") ;
+    res->regex.nfiles = x ;
+    x = resolve_find_cdb(&tmp,c,"ninfiles") ;
+    res->regex.ninfiles = x ;
 
-    /* disen */
-    x = resolve_find_cdb(&tmp,c,"disen") ;
-    res->disen = x ;
 
     free(wres) ;
     stralloc_free(&tmp) ;
diff --git a/src/lib66/service/service_resolve_sort_bytype.c b/src/lib66/service/service_resolve_sort_bytype.c
index 1e7a9a88..619197e3 100644
--- a/src/lib66/service/service_resolve_sort_bytype.c
+++ b/src/lib66/service/service_resolve_sort_bytype.c
@@ -19,8 +19,18 @@
 #include <skalibs/stralloc.h>
 
 #include <66/resolve.h>
+#include <66/enum.h>
 #include <66/service.h>
-
+/***
+ *
+ *
+ *
+ * may not be used anymore
+ *
+ *
+ *
+ *
+ * */
 int service_resolve_sort_bytype(stralloc *list, char const *src)
 {
     log_flow() ;
@@ -70,7 +80,6 @@ int service_resolve_sort_bytype(stralloc *list, char const *src)
                 break ;
 
             case TYPE_BUNDLE:
-            case TYPE_LONGRUN:
             case TYPE_ONESHOT:
 
                 if (!stralloc_insertb(list, module_list, name, strlen(name) + 1))
diff --git a/src/lib66/service/service_resolve_write.c b/src/lib66/service/service_resolve_write.c
new file mode 100644
index 00000000..ebdf0394
--- /dev/null
+++ b/src/lib66/service/service_resolve_write.c
@@ -0,0 +1,58 @@
+/*
+ * service_resolve_write.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <66/service.h>
+#include <66/resolve.h>
+#include <66/constants.h>
+
+int service_resolve_write(resolve_service_t *res)
+{
+    log_flow() ;
+
+    int r, e = 0 ;
+
+    char *name = res->sa.s + res->name ;
+    size_t namelen = strlen(name) ;
+    char sym[strlen(res->sa.s + res->path.home) + SS_SYSTEM_LEN + SS_RESOLVE_LEN + 1 + SS_SERVICE_LEN + 1 + namelen + 1] ;
+    char dst[strlen(res->sa.s + res->path.tree) + SS_SVDIRS_LEN + 1] ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ;
+
+    auto_strings(sym, res->sa.s + res->path.home, SS_SYSTEM, SS_RESOLVE, "/", SS_SERVICE, "/", name) ;
+
+    auto_strings(dst, res->sa.s + res->path.tree, SS_SVDIRS) ;
+
+    if (!resolve_write(wres, dst, name))
+        goto err ;
+
+    r = symlink(dst, sym) ;
+    if (r < 0 && errno != EEXIST) {
+        log_warnusys("point symlink: ", sym, " to: ", dst) ;
+        goto err ;
+    }
+
+    e = 1 ;
+
+    err:
+        free(wres) ;
+        return e ;
+}
+
+
diff --git a/src/lib66/service/service_resolve_write_cdb.c b/src/lib66/service/service_resolve_write_cdb.c
index b68f3dd6..b89057cb 100644
--- a/src/lib66/service/service_resolve_write_cdb.c
+++ b/src/lib66/service/service_resolve_write_cdb.c
@@ -26,107 +26,92 @@ int service_resolve_write_cdb(cdbmaker *c, resolve_service_t *sres)
 
     char *str = sres->sa.s ;
 
-    /* name */
-    if (!resolve_add_cdb(c,"name",str + sres->name) ||
-
-    /* description */
-    !resolve_add_cdb(c,"description",str + sres->description) ||
-
-    /* version */
-    !resolve_add_cdb(c,"version",str + sres->version) ||
-
-    /* logger */
-    !resolve_add_cdb(c,"logger",str + sres->logger) ||
-
-    /* logreal */
-    !resolve_add_cdb(c,"logreal",str + sres->logreal) ||
-
-    /* logassoc */
-    !resolve_add_cdb(c,"logassoc",str + sres->logassoc) ||
-
-    /* dstlog */
-    !resolve_add_cdb(c,"dstlog",str + sres->dstlog) ||
-
-    /* depends */
-    !resolve_add_cdb(c,"depends",str + sres->depends) ||
-
-    /* deps */
-    !resolve_add_cdb(c,"requiredby",str + sres->requiredby) ||
-
-    /* optsdeps */
-    !resolve_add_cdb(c,"optsdeps",str + sres->optsdeps) ||
-
-    /* extdeps */
-    !resolve_add_cdb(c,"extdeps",str + sres->extdeps) ||
-
-    /* contents */
-    !resolve_add_cdb(c,"contents",str + sres->contents) ||
-
-    /* src */
-    !resolve_add_cdb(c,"src",str + sres->src) ||
-
-    /* srconf */
-    !resolve_add_cdb(c,"srconf",str + sres->srconf) ||
-
-    /* live */
-    !resolve_add_cdb(c,"live",str + sres->live) ||
-
-    /* runat */
-    !resolve_add_cdb(c,"runat",str + sres->runat) ||
-
-    /* tree */
-    !resolve_add_cdb(c,"tree",str + sres->tree) ||
-
-    /* treename */
-    !resolve_add_cdb(c,"treename",str + sres->treename) ||
-
-    /* dstlog */
-    !resolve_add_cdb(c,"dstlog",str + sres->dstlog) ||
-
-    /* state */
-    !resolve_add_cdb(c,"state",str + sres->state) ||
-
-    /* exec_run */
-    !resolve_add_cdb(c,"exec_run",str + sres->exec_run) ||
-
-    /* exec_log_run */
-    !resolve_add_cdb(c,"exec_log_run",str + sres->exec_log_run) ||
-
-    /* real_exec_run */
-    !resolve_add_cdb(c,"real_exec_run",str + sres->real_exec_run) ||
-
-    /* real_exec_log_run */
-    !resolve_add_cdb(c,"real_exec_log_run",str + sres->real_exec_log_run) ||
-
-    /* exec_finish */
-    !resolve_add_cdb(c,"exec_finish",str + sres->exec_finish) ||
-
-    /* real_exec_finish */
-    !resolve_add_cdb(c,"real_exec_finish",str + sres->real_exec_finish) ||
-
-    /* type */
-    !resolve_add_cdb_uint(c,"type",sres->type) ||
-
-    /* ndepends */
-    !resolve_add_cdb_uint(c,"ndepends",sres->ndepends) ||
-
-    /* ndeps */
-    !resolve_add_cdb_uint(c,"ndeps",sres->nrequiredby) ||
-
-    /* noptsdeps */
-    !resolve_add_cdb_uint(c,"noptsdeps",sres->noptsdeps) ||
-
-    /* nextdeps */
-    !resolve_add_cdb_uint(c,"nextdeps",sres->nextdeps) ||
-
-    /* ncontents */
-    !resolve_add_cdb_uint(c,"ncontents",sres->ncontents) ||
-
-    /* down */
-    !resolve_add_cdb_uint(c,"down",sres->down) ||
-
-    /* disen */
-    !resolve_add_cdb_uint(c,"disen",sres->disen)) return 0 ;
+    // configuration
+    if (!resolve_add_cdb(c, "name", str + sres->name) ||
+    !resolve_add_cdb(c, "description", str + sres->description) ||
+    !resolve_add_cdb(c, "version", str + sres->version) ||
+    !resolve_add_cdb_uint(c, "type", sres->type) ||
+    !resolve_add_cdb_uint(c, "notify", sres->notify) ||
+    !resolve_add_cdb_uint(c, "maxdeath", sres->maxdeath) ||
+    !resolve_add_cdb_uint(c, "earlier", sres->earlier) ||
+    !resolve_add_cdb(c, "hiercopy", str + sres->hiercopy) ||
+    !resolve_add_cdb(c, "intree", str + sres->intree) ||
+    !resolve_add_cdb(c, "ownerstr", str + sres->ownerstr) ||
+    !resolve_add_cdb_uint(c, "owner", sres->owner) ||
+    !resolve_add_cdb(c, "treename", str + sres->treename) ||
+    !resolve_add_cdb(c, "user", str + sres->user) ||
+    !resolve_add_cdb(c, "inmodule", str + sres->inmodule) ||
+
+    // path
+    !resolve_add_cdb(c, "home", str + sres->path.home) ||
+    !resolve_add_cdb(c, "frontend", str + sres->path.frontend) ||
+    !resolve_add_cdb(c, "tree", str + sres->path.tree) ||
+    !resolve_add_cdb(c, "status", str + sres->path.status) ||
+
+    // dependencies
+    !resolve_add_cdb(c, "depends", str + sres->dependencies.depends) ||
+    !resolve_add_cdb(c, "requiredby", str + sres->dependencies.requiredby) ||
+    !resolve_add_cdb(c, "optsdeps", str + sres->dependencies.optsdeps) ||
+    !resolve_add_cdb_uint(c, "ndepends", sres->dependencies.ndepends) ||
+    !resolve_add_cdb_uint(c, "nrequiredby", sres->dependencies.nrequiredby) ||
+    !resolve_add_cdb_uint(c, "noptsdeps", sres->dependencies.noptsdeps) ||
+
+    // execute
+    !resolve_add_cdb(c, "run", str + sres->execute.run.run) ||
+    !resolve_add_cdb(c, "run_user", str + sres->execute.run.run_user) ||
+    !resolve_add_cdb(c, "run_build", str + sres->execute.run.build) ||
+    !resolve_add_cdb(c, "run_shebang", str + sres->execute.run.shebang) ||
+    !resolve_add_cdb(c, "run_runas", str + sres->execute.run.runas) ||
+    !resolve_add_cdb(c, "finish", str + sres->execute.finish.run) ||
+    !resolve_add_cdb(c, "finish_user", str + sres->execute.finish.run_user) ||
+    !resolve_add_cdb(c, "finish_build", str + sres->execute.finish.build) ||
+    !resolve_add_cdb(c, "finish_shebang", str + sres->execute.finish.shebang) ||
+    !resolve_add_cdb(c, "finish_runas", str + sres->execute.finish.runas) ||
+    !resolve_add_cdb_uint(c, "timeoutkill", sres->execute.timeout.kill) ||
+    !resolve_add_cdb_uint(c, "timeoutfinish", sres->execute.timeout.finish) ||
+    !resolve_add_cdb_uint(c, "timeoutup", sres->execute.timeout.up) ||
+    !resolve_add_cdb_uint(c, "timeoutdown", sres->execute.timeout.down) ||
+    !resolve_add_cdb_uint(c, "down", sres->execute.down) ||
+    !resolve_add_cdb_uint(c, "downsignal", sres->execute.downsignal) ||
+
+    //live
+    !resolve_add_cdb(c, "livedir", str + sres->live.livedir) ||
+    !resolve_add_cdb(c, "scandir", str + sres->live.scandir) ||
+    !resolve_add_cdb(c, "statedir", str + sres->live.statedir) ||
+    !resolve_add_cdb(c, "eventdir", str + sres->live.eventdir) ||
+    !resolve_add_cdb(c, "notifdir", str + sres->live.notifdir) ||
+    !resolve_add_cdb(c, "supervisedir", str + sres->live.supervisedir) ||
+    !resolve_add_cdb(c, "fdholderdir", str + sres->live.fdholderdir) ||
+    !resolve_add_cdb(c, "oneshotddir", str + sres->live.oneshotddir) ||
+
+    // logger
+    !resolve_add_cdb(c, "logname", str + sres->logger.name) ||
+    !resolve_add_cdb(c, "logdestination", str + sres->logger.destination) ||
+    !resolve_add_cdb_uint(c, "logbackup", sres->logger.backup) ||
+    !resolve_add_cdb_uint(c, "logmaxsize", sres->logger.maxsize) ||
+    !resolve_add_cdb_uint(c, "logwant", sres->logger.want) ||
+    !resolve_add_cdb_uint(c, "logtimestamp", sres->logger.timestamp) ||
+    !resolve_add_cdb(c, "logrun", str + sres->logger.execute.run.run) ||
+    !resolve_add_cdb(c, "logrun_user", str + sres->logger.execute.run.run_user) ||
+    !resolve_add_cdb(c, "logrun_build", str + sres->logger.execute.run.build) ||
+    !resolve_add_cdb(c, "logrun_shebang", str + sres->logger.execute.run.shebang) ||
+    !resolve_add_cdb(c, "logrun_runas", str + sres->logger.execute.run.runas) ||
+    !resolve_add_cdb_uint(c, "logtimeoutkill", sres->logger.execute.timeout.kill) ||
+    !resolve_add_cdb_uint(c, "logtimeoutfinish", sres->logger.execute.timeout.finish) ||
+
+    // environ
+    !resolve_add_cdb(c, "env", str + sres->environ.env) ||
+    !resolve_add_cdb(c, "envdir", str + sres->environ.envdir) ||
+    !resolve_add_cdb_uint(c, "env_overwrite", sres->environ.env_overwrite) ||
+
+    // regex
+    !resolve_add_cdb(c, "configure", str + sres->regex.configure) ||
+    !resolve_add_cdb(c, "directories", str + sres->regex.directories) ||
+    !resolve_add_cdb(c, "files", str + sres->regex.files) ||
+    !resolve_add_cdb(c, "infiles", str + sres->regex.infiles) ||
+    !resolve_add_cdb_uint(c, "ndirectories", sres->regex.ndirectories) ||
+    !resolve_add_cdb_uint(c, "nfiles", sres->regex.nfiles) ||
+    !resolve_add_cdb_uint(c, "ninfiles", sres->regex.ninfiles)) return 0 ;
 
     return 1 ;
 }
-- 
GitLab