From 9af7a2f04cf768a3227d5fc8f7d5492f106b392e Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Mon, 1 May 2023 18:44:25 +1100
Subject: [PATCH] revamp module

---
 src/include/66/module.h          |   8 +-
 src/lib66/module/get_list.c      |   6 +-
 src/lib66/module/parse_module.c  | 168 +++++++++++++++++--------------
 src/lib66/parse/parse_frontend.c |  30 ++++--
 4 files changed, 121 insertions(+), 91 deletions(-)

diff --git a/src/include/66/module.h b/src/include/66/module.h
index 00d40303..eddd6e7d 100644
--- a/src/include/66/module.h
+++ b/src/include/66/module.h
@@ -26,10 +26,10 @@
 #define SS_MODULE_CONFIG_DIR_LEN (sizeof SS_MODULE_CONFIG_DIR - 1)
 #define SS_MODULE_CONFIG_SCRIPT "configure"
 #define SS_MODULE_CONFIG_SCRIPT_LEN (sizeof SS_MODULE_CONFIG_SCRIPT - 1)
-#define SS_MODULE_SERVICE "/service"
-#define SS_MODULE_SERVICE_LEN (sizeof SS_MODULE_SERVICE - 1)
-#define SS_MODULE_SERVICE_INSTANCE "/service@"
-#define SS_MODULE_SERVICE_INSTANCE_LEN (sizeof SS_MODULE_SERVICE_INSTANCE - 1)
+#define SS_MODULE_FRONTEND "/frontend"
+#define SS_MODULE_FRONTEND_LEN (sizeof SS_MODULE_FRONTEND - 1)
+#define SS_MODULE_ACTIVATED "/activated"
+#define SS_MODULE_ACTIVATED_LEN (sizeof SS_MODULE_ACTIVATED - 1)
 
 extern void get_list(stralloc *list, char const *src, char const *name, mode_t mode) ;
 extern void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force) ;
diff --git a/src/lib66/module/get_list.c b/src/lib66/module/get_list.c
index 930482ad..680b5fdb 100644
--- a/src/lib66/module/get_list.c
+++ b/src/lib66/module/get_list.c
@@ -29,11 +29,7 @@ void get_list(stralloc *list, char const *src, char const *name, mode_t mode)
     list->len = 0 ;
     char const *exclude[2] = { SS_MODULE_CONFIG_DIR + 1, 0 } ;
 
-    char t[strlen(src) + 1] ;
-
-    auto_strings(t, src) ;
-
-    if (!sastr_dir_get_recursive(list, t, exclude, mode, 1))
+    if (!sastr_dir_get_recursive(list, src, exclude, mode, 1))
         log_dieusys(LOG_EXIT_SYS,"get file(s) of module: ", name) ;
 
 }
diff --git a/src/lib66/module/parse_module.c b/src/lib66/module/parse_module.c
index 2980ac18..63fb5c3e 100644
--- a/src/lib66/module/parse_module.c
+++ b/src/lib66/module/parse_module.c
@@ -13,6 +13,7 @@
  */
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -100,12 +101,12 @@ void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int
     log_flow() ;
 
     int r, insta = -1 ;
-    size_t pos = 0, pathlen = 0 ;
+    size_t pos = 0, copylen = 0, len = 0 ;
     char name[strlen(res->sa.s + res->name) + 1] ;
     auto_strings(name,res->sa.s + res->name) ;
     char *src = res->sa.s + res->path.frontend ;
-    char dirname[strlen(src) + 1] ;
-    char path[SS_MAX_PATH_LEN] ;
+    char dirname[strlen(src)] ;
+    char copy[SS_MAX_PATH_LEN] ;
     char ainsta[strlen(name)] ;
     stralloc list = STRALLOC_ZERO ;
     resolve_wrapper_t_ref wres = 0 ;
@@ -120,34 +121,32 @@ void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int
 
     if (!getuid()) {
 
-        auto_strings(path, SS_SERVICE_ADMDIR, name) ;
+        auto_strings(copy, SS_SERVICE_ADMDIR, name) ;
 
     } else {
 
-        if (!set_ownerhome_stack(path))
+        if (!set_ownerhome_stack(copy))
             log_dieusys(LOG_EXIT_SYS, "unable to find the home directory of the user") ;
 
-        pathlen = strlen(path) ;
-        auto_strings(path + pathlen, SS_SERVICE_USERDIR, name) ;
+        auto_strings(copy + copylen, SS_SERVICE_USERDIR, name) ;
     }
 
     uint8_t conf = res->environ.env_overwrite ;
 
-    /** check mandatory directories
-     * res->frontend/module_name/{configure,service,service@} */
+    /** check mandatory directories */
     parse_module_check_dir(dirname, SS_MODULE_CONFIG_DIR) ;
-    parse_module_check_dir(dirname, SS_MODULE_SERVICE) ;
-    parse_module_check_dir(dirname, SS_MODULE_SERVICE_INSTANCE) ;
+    parse_module_check_dir(dirname, SS_MODULE_ACTIVATED) ;
+    parse_module_check_dir(dirname, SS_MODULE_FRONTEND) ;
 
-    r = scan_mode(path, S_IFDIR) ;
+    r = scan_mode(copy, S_IFDIR) ;
     if (r == -1) {
         errno = EEXIST ;
-        log_dieusys(LOG_EXIT_SYS, "conflicting format of: ", path) ;
+        log_dieusys(LOG_EXIT_SYS, "conflicting format of: ", copy) ;
 
     } else if (!r) {
 
-        if (!hiercopy(dirname, path))
-            log_dieusys(LOG_EXIT_SYS, "copy: ", dirname, " to: ", path) ;
+        if (!hiercopy(dirname, copy))
+            log_dieusys(LOG_EXIT_SYS, "copy: ", dirname, " to: ", copy) ;
 
     } else {
 
@@ -158,119 +157,136 @@ void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int
             goto deps ;
         }
 
-        log_trace("remove directory: ", path) ;
+        log_trace("remove directory: ", copy) ;
 
-        if (!dir_rm_rf(path))
-            log_dieusys (LOG_EXIT_SYS, "remove: ", path) ;
+        if (!dir_rm_rf(copy))
+            log_dieusys (LOG_EXIT_SYS, "remove: ", copy) ;
 
-        if (!hiercopy(dirname, path))
-            log_dieusys(LOG_EXIT_SYS,"copy: ", dirname, " to: ", path) ;
+        log_trace("copy: ", dirname, " to: ", copy) ;
+        if (!hiercopy(dirname, copy))
+            log_dieusys(LOG_EXIT_SYS,"copy: ", dirname, " to: ", copy) ;
     }
 
-    pathlen = strlen(path) ;
+    copylen = strlen(copy) ;
+
+    auto_strings(copy + copylen, "/", ainsta) ;
+
     /** remove the original service frontend file inside the copied directory
      * to avoid double frontend service file for a same service.*/
-    auto_strings(path + pathlen, "/", ainsta) ;
+    errno = 0 ;
+    if (unlink(copy) < 0 && errno != ENOENT)
+        log_dieusys(LOG_EXIT_ZERO, "unlink: ", copy) ;
 
-    if (unlink(path) < 0)
-        log_dieusys(LOG_EXIT_ZERO, "unlink: ", path) ;
+    copy[copylen] = 0 ;
 
-    path[pathlen] = 0 ;
+    auto_strings(copy + copylen, SS_MODULE_FRONTEND) ;
 
     /** contents */
-    get_list(&list, path, name, S_IFREG) ;
+    get_list(&list, copy, name, S_IFREG) ;
     regex_replace(&list, res) ;
 
+    copy[copylen] = 0 ;
+
     /** directories */
-    get_list(&list, path, name, S_IFDIR) ;
+    get_list(&list, copy, name, S_IFDIR) ;
     regex_rename(&list, res, res->regex.directories) ;
 
     /** filename */
-    get_list(&list, path, name, S_IFREG) ;
+    get_list(&list, copy, name, S_IFREG) ;
     regex_rename(&list, res, res->regex.files) ;
 
     /** configure script */
-    regex_configure(res, info, path, name) ;
+    regex_configure(res, info, copy, name) ;
 
     deps:
 
-    list.len = 0 ;
+    auto_strings(copy + copylen, SS_MODULE_ACTIVATED) ;
 
-    if (!auto_stra(&list, path))
-        log_die_nomem("stralloc") ;
+    get_list(&list, copy, name, S_IFREG) ;
 
-    char t[list.len] ;
+    auto_strings(copy + copylen, SS_MODULE_FRONTEND) ;
 
-    sastr_to_char(t, &list) ;
+    {
+        /* parse each activated services */
+        len = list.len ;
+        char l[len + 1] ;
+        stralloc sa = STRALLOC_ZERO ;
 
-    list.len = 0 ;
-    char const *exclude[3] = { SS_MODULE_CONFIG_DIR + 1, SS_MODULE_SERVICE_INSTANCE + 1, 0 } ;
+        sastr_to_char(l, &list) ;
 
-    if (!sastr_dir_get_recursive(&list, t, exclude, S_IFREG, 1))
-        log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", name) ;
+        list.len = 0 ;
 
-    char ll[list.len] ;
-    size_t llen = list.len ;
+        for (pos = 0 ; pos < len ; pos += strlen(l + pos) + 1) {
 
-    sastr_to_char(ll, &list) ;
+            sa.len = 0 ;
 
-    list.len = 0 ;
+            char fname[strlen(l + pos)] ;
 
-    for (pos = 0 ; pos < llen ; pos += strlen(ll + pos) + 1) {
+            if (!ob_basename(fname, l + pos))
+                log_dieusys(LOG_EXIT_ZERO, "basename of: ", l + pos) ;
 
-        char *dname = ll + pos ;
-        char ainsta[pathlen + SS_MODULE_SERVICE_INSTANCE_LEN + 1 + SS_MAX_SERVICE_NAME + 1] ;
-        size_t dlen = strlen(dname) ;
-        char bname[dlen] ;
+            /** cannot call itself */
+            if (!strcmp(name, fname))
+                log_die(LOG_EXIT_SYS, "cyclic call detected -- ", name, " call ", fname) ;
 
-        if (!ob_basename(bname,dname))
-            log_dieu(LOG_EXIT_SYS, "find basename of: ", dname) ;
+            /** Search first inside the frontend directory.
+             * If not found, search in the entire system. */
 
-        if (instance_check(bname) > 0) {
-            auto_strings(ainsta, path, SS_MODULE_SERVICE_INSTANCE, "/", bname) ;
-            dname = ainsta ;
-        }
+            if (!service_frontend_path(&sa, fname, info->owner, copy)) {
 
-        if (!strcmp(name, bname))
-            log_die(LOG_EXIT_SYS, "cyclic call detected -- ", name, " call ", bname) ;
+                if (!service_frontend_path(&sa, fname, info->owner, 0))
+                    log_dieu(LOG_EXIT_USER, "find service frontend file of: ", fname) ;
 
-        char n[strlen(name) + 1 + strlen(bname) + 1] ;
+                /*if (!hiercopy(sa.s, copy))
+                    log_dieusys(LOG_EXIT_SYS, "copy: ", sa.s, " to: ", copy) ;
+                */
+            }
 
-        auto_strings(n, name, ":", bname) ;
+            char n[strlen(name) + 1 + strlen(fname) + 1] ;
 
-        if (!sastr_add_string(&list, n))
-            log_die_nomem("stralloc") ;
+            auto_strings(n, name, ":", fname) ;
+
+            if (!sastr_add_string(&list, n))
+                log_die_nomem("stralloc") ;
 
-        parse_frontend(dname, ares, areslen, info, force, conf, path, bname, name) ;
+            parse_frontend(sa.s, ares, areslen, info, force, conf, copy, fname, name) ;
+        }
+
+        stralloc_free(&sa) ;
     }
 
-    llen = list.len ;
+    {
+        /* make a good list of dependencies/requiredby*/
+        len = list.len ;
 
-    sastr_to_char(ll, &list) ;
+        char l[len + 1] ;
 
-    list.len = 0 ;
+        sastr_to_char(l, &list) ;
 
-    for (pos = 0 ; pos < llen ; pos += strlen(ll + pos) + 1) {
+        list.len = 0 ;
 
-        int aresid = service_resolve_array_search(ares, *areslen, ll + pos) ;
-        if (aresid < 0)
-            log_die(LOG_EXIT_USER, "service: ",ll + pos, " not available -- please make a bug report") ;
+        for (pos = 0 ; pos < len ; pos += strlen(l + pos) + 1) {
 
-        if (ares[aresid].dependencies.ndepends || ares[aresid].dependencies.nrequiredby)
-            convert_tomodule(&ares[aresid], name) ;
+            int aresid = service_resolve_array_search(ares, *areslen, l + pos) ;
+            if (aresid < 0)
+                log_die(LOG_EXIT_USER, "service: ", l + pos, " not available -- please make a bug report") ;
 
-        if (ares[aresid].logger.want && ares[aresid].type == TYPE_CLASSIC) {
+            if (ares[aresid].dependencies.ndepends || ares[aresid].dependencies.nrequiredby)
+                convert_tomodule(&ares[aresid], name) ;
 
-            char n[strlen(ares[aresid].sa.s + ares[aresid].name) + SS_LOG_SUFFIX_LEN + 1] ;
+            if (ares[aresid].logger.want && ares[aresid].type == TYPE_CLASSIC) {
 
-            auto_strings(n, ares[aresid].sa.s + ares[aresid].name, SS_LOG_SUFFIX) ;
+                char n[strlen(ares[aresid].sa.s + ares[aresid].name) + SS_LOG_SUFFIX_LEN + 1] ;
 
-            if (!sastr_add_string(&list, n))
+                auto_strings(n, ares[aresid].sa.s + ares[aresid].name, SS_LOG_SUFFIX) ;
+
+                if (!sastr_add_string(&list, n))
+                    log_die_nomem("stralloc") ;
+            }
+
+            if (!sastr_add_string(&list, l + pos))
                 log_die_nomem("stralloc") ;
         }
-
-        if (!sastr_add_string(&list, ll + pos))
-            log_die_nomem("stralloc") ;
     }
 
     wres = resolve_set_struct(DATA_SERVICE, res) ;
diff --git a/src/lib66/parse/parse_frontend.c b/src/lib66/parse/parse_frontend.c
index f29b18e9..30576889 100644
--- a/src/lib66/parse/parse_frontend.c
+++ b/src/lib66/parse/parse_frontend.c
@@ -48,10 +48,28 @@ static void parse_service_instance(stralloc *frontend, char const *svsrc, char c
     if (!instance_splitname(&sa, sv, insta, SS_INSTANCE_TEMPLATE))
         log_die(LOG_EXIT_SYS, "split instance service of: ", sv) ;
 
-    log_trace("read frontend service of: ", svsrc, sv) ;
+    log_trace("read frontend service at: ", svsrc, sa.s) ;
 
-    if (read_svfile(frontend, sa.s, svsrc) <= 0)
-        log_dieusys(LOG_EXIT_SYS, "read frontend service of: ", svsrc, sa.s) ;
+    if (read_svfile(frontend, sa.s, svsrc) <= 0) {
+
+        char instaname[sa.len + 1] ;
+        auto_strings(instaname, sa.s) ;
+        sa.len = 0 ;
+        /** in module the template service may not exist e.g.
+         * module which call another module. In this case
+         * follow the classic way */
+        int r = service_frontend_path(&sa, sv, getuid(), 0) ;
+        if (r < 1)
+            log_dieu(LOG_EXIT_SYS, "get frontend service file of: ", sv) ;
+
+        char svsrc[sa.len + 1] ;
+
+        if (!ob_dirname(svsrc, sa.s))
+            log_dieu(LOG_EXIT_SYS, "get dirname of: ", sa.s) ;
+
+        if (read_svfile(frontend, instaname, svsrc) <= 0)
+            log_dieusys(LOG_EXIT_SYS, "read frontend service at: ", svsrc, instaname) ;
+    }
 
     stralloc_free(&sa) ;
 
@@ -110,10 +128,10 @@ int parse_frontend(char const *sv, resolve_service_t *ares, unsigned int *aresle
 
     } else {
 
-        log_trace("read frontend service of: ", sv) ;
+        log_trace("read frontend service at: ", sv) ;
 
         if (read_svfile(&sa, svname, svsrc) <= 0)
-            log_dieusys(LOG_EXIT_SYS, "read frontend service of: ", sv) ;
+            log_dieusys(LOG_EXIT_SYS, "read frontend service at: ", sv) ;
     }
 
     char file[sa.len + 1] ;
@@ -238,7 +256,6 @@ int parse_frontend(char const *sv, resolve_service_t *ares, unsigned int *aresle
         if (*areslen >= SS_MAX_SERVICE)
             log_die(LOG_EXIT_SYS, "too many services to parse -- compile again 66 changing the --max-service options") ;
         ares[(*areslen)++] = res ;
-
     }
 
     freed:
@@ -246,3 +263,4 @@ int parse_frontend(char const *sv, resolve_service_t *ares, unsigned int *aresle
         free(wres) ;
         return 1 ;
 }
+
-- 
GitLab