diff --git a/src/include/66/module.h b/src/include/66/module.h
new file mode 100644
index 0000000000000000000000000000000000000000..591025343b7a16b63c21a23942adf7cd2b4b061c
--- /dev/null
+++ b/src/include/66/module.h
@@ -0,0 +1,45 @@
+/*
+ * module.h
+ *
+ * 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./
+ */
+
+#ifndef SS_MODULE_H
+#define SS_MODULE_H
+
+#include <sys/types.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/service.h>
+#include <66/info.h>
+
+#define SS_MODULE_CONFIG_DIR "/configure"
+#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)
+
+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) ;
+extern void parse_module_check_dir(char const *src,char const *dir) ;
+extern void parse_module_check_name(char const *src, char const *name) ;
+extern void regex_configure(resolve_service_t *res, ssexec_t *info, char const *path, char const *name) ;
+extern int regex_get_file_name(char *filename, char const *str) ;
+extern void regex_get_regex(char *regex, char const *str) ;
+extern void regex_get_replace(char *replace, char const *str) ;
+extern void regex_rename(stralloc *list, resolve_service_t *res, uint32_t element) ;
+extern void regex_replace(stralloc *list, resolve_service_t *res) ;
+
+#endif
diff --git a/src/lib66/module/deps-lib/deps b/src/lib66/module/deps-lib/deps
index aa08a1493330806f8a201d878aa14bb087db05a3..a513575fd778a1593d20164b37fd04393134bbab 100644
--- a/src/lib66/module/deps-lib/deps
+++ b/src/lib66/module/deps-lib/deps
@@ -1,3 +1,12 @@
+get_list.o
+parse_module.o
+parse_module_check_dir.o
+regex_configure.o
+regex_get_file_name.o
+regex_get_regex.o
+regex_get_replace.o
+regex_rename.o
+regex_replace.o
 -loblibs
 -lskarnet
 
diff --git a/src/lib66/module/get_list.c b/src/lib66/module/get_list.c
new file mode 100644
index 0000000000000000000000000000000000000000..930482ad84430b09690b09d452179a48b8f3adcf
--- /dev/null
+++ b/src/lib66/module/get_list.c
@@ -0,0 +1,39 @@
+/*
+ * regex_get_replace.c
+ *
+ * Copyright (c) 2018-2022 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 <sys/types.h>
+#include <string.h>
+
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/module.h>
+
+void get_list(stralloc *list, char const *src, char const *name, mode_t mode)
+{
+    log_flow() ;
+
+    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))
+        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
new file mode 100644
index 0000000000000000000000000000000000000000..26d49e32cdbafbe39e189844861fd35b34b0f10f
--- /dev/null
+++ b/src/lib66/module/parse_module.c
@@ -0,0 +1,226 @@
+/*
+ * parse_module.c
+ *
+ * Copyright (c) 2018-2022 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 <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> //chdir, unlink
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/sastr.h>
+#include <oblibs/directory.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h> //hiercopy
+
+#include <66/module.h>
+#include <66/resolve.h>
+#include <66/info.h>
+#include <66/constants.h>
+#include <66/instance.h>
+#include <66/utils.h>
+#include <66/parser.h>
+
+void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force)
+{
+    log_flow() ;
+
+    int r, insta = -1 ;
+    unsigned int residx = 0 ;
+    size_t pos = 0, pathlen = 0 ;
+    char *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 ainsta[strlen(name)] ;
+    stralloc list = STRALLOC_ZERO ;
+    resolve_wrapper_t_ref wres = 0 ;
+
+    log_trace("parse module: ", name) ;
+
+    if (!ob_dirname(dirname, src))
+        log_dieu(LOG_EXIT_SYS, "get directory name of: ", src) ;
+
+    insta = instance_check(name) ;
+    instance_splitname_to_char(ainsta, name, insta, 0) ;
+
+    size_t prefixlen = strlen(name) ;
+
+    char prefix[prefixlen + 2] ;
+
+    instance_splitname_to_char(prefix, name, insta, 1) ;
+
+    auto_strings(prefix + strlen(prefix), "-") ;
+    prefixlen = strlen(prefix) ;
+
+    if (!getuid()) {
+
+        auto_strings(path, SS_SERVICE_ADMDIR, name) ;
+
+    } else {
+
+        if (!set_ownerhome_stack(path))
+            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) ;
+    }
+
+    uint8_t conf = res->environ.env_overwrite ;
+
+    /** check mandatory directories
+     * res->frontend/module_name/{configure,service,service@} */
+    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) ;
+
+    r = scan_mode(path, S_IFDIR) ;
+    if (r == -1) {
+        errno = EEXIST ;
+        log_dieusys(LOG_EXIT_SYS, "conflicting format of: ", path) ;
+
+    } else if (!r) {
+
+        if (!hiercopy(dirname, path))
+            log_dieusys(LOG_EXIT_SYS, "copy: ", dirname, " to: ", path) ;
+
+    } else {
+
+        /** Must reconfigure all services of the module */
+        if (force < 1) {
+
+            log_warn("skip configuration of the module: ", name, " -- already configured") ;
+            goto deps ;
+        }
+
+        if (dir_rm_rf(path) < 0)
+            log_dieusys (LOG_EXIT_SYS, "remove: ", path) ;
+
+        if (!hiercopy(dirname, path))
+            log_dieusys(LOG_EXIT_SYS,"copy: ", dirname, " to: ", path) ;
+    }
+
+    pathlen = strlen(path) ;
+    /** 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) ;
+
+    if (unlink(path) < 0)
+        log_dieusys(LOG_EXIT_ZERO, "unlink: ", path) ;
+
+    path[pathlen] = 0 ;
+
+    /** contents */
+    get_list(&list, path, name, S_IFREG) ;
+    regex_replace(&list, res) ;
+
+    /** directories */
+    get_list(&list, path, name, S_IFDIR) ;
+    regex_rename(&list, res, res->regex.directories) ;
+
+    /** filename */
+    get_list(&list, path, name, S_IFREG) ;
+    regex_rename(&list, res, res->regex.files) ;
+
+    /** configure script */
+    regex_configure(res, info, path, name) ;
+
+    deps:
+
+    list.len = 0 ;
+
+    if (!auto_stra(&list, path))
+        log_die_nomem("stralloc") ;
+
+    char t[list.len] ;
+
+    sastr_to_char(t, &list) ;
+
+    list.len = 0 ;
+    char const *exclude[3] = { SS_MODULE_CONFIG_DIR + 1, SS_MODULE_SERVICE_INSTANCE + 1, 0 } ;
+    if (!sastr_dir_get_recursive(&list, t, exclude, S_IFREG, 1))
+        log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", name) ;
+
+    char ll[list.len] ;
+    size_t llen = list.len ;
+
+    sastr_to_char(ll, &list) ;
+
+    list.len = 0 ;
+
+    for (pos = 0 ; pos < llen ; pos += strlen(ll + pos) + 1) {
+
+        char *dname = ll + pos ;
+        char ainsta[pathlen + SS_MODULE_SERVICE_INSTANCE_LEN + 1 + SS_MAX_SERVICE_NAME + 1] ;
+        size_t namelen = strlen(dname) ;
+        char bname[namelen] ;
+
+        if (!ob_basename(bname,dname))
+            log_dieu(LOG_EXIT_SYS, "find basename of: ", dname) ;
+
+        if (instance_check(bname) > 0) {
+            auto_strings(ainsta, path, SS_MODULE_SERVICE_INSTANCE, "/", bname) ;
+            dname = ainsta ;
+        }
+
+        if (!sastr_add_string(&list, bname))
+            log_die_nomem("stralloc") ;
+
+        if (!strcmp(name, bname))
+            log_die(LOG_EXIT_SYS, "cyclic call detected -- ", name, " call ", bname) ;
+
+        /** nothing to do with the exit code*/
+        parse_frontend(dname, ares, areslen, info, force, conf, &residx, path, bname) ;
+
+        wres = resolve_set_struct(DATA_SERVICE, &ares[residx]) ;
+
+        ares[residx].inmodule = resolve_add_string(wres, name) ;
+    }
+
+    char deps[list.len] ;
+
+    sastr_to_char(deps, &list) ;
+
+    llen = list.len ;
+
+    list.len = 0 ;
+
+    /* rebuild the dependencies list incorporating the services defined inside
+     * the module.
+
+    if (res->dependencies.ndepends)
+        if (!sastr_clean_string(&list, res->sa.s + res->dependencies.depends))
+            log_dieu(LOG_EXIT_SYS, "clean string") ;
+
+
+
+    res->dependencies.depends = parse_compute_list(wres, &list, &res->dependencies.ndepends, 0) ;
+
+    list.len = 0 ;
+*/
+
+    wres = resolve_set_struct(DATA_SERVICE, res) ;
+
+    for (pos = 0 ; pos < llen ; pos += strlen(deps + pos) + 1)
+        if (!sastr_add_string(&list, deps + pos))
+            log_die_nomem("stralloc") ;
+
+    res->regex.contents = parse_compute_list(wres, &list, &res->regex.ncontents, 0) ;
+
+    free(wres) ;
+    stralloc_free(&list) ;
+}
diff --git a/src/lib66/module/parse_module_check_dir.c b/src/lib66/module/parse_module_check_dir.c
new file mode 100644
index 0000000000000000000000000000000000000000..28cc2eba6bc754fcdf4803476e857f010128b8a1
--- /dev/null
+++ b/src/lib66/module/parse_module_check_dir.c
@@ -0,0 +1,43 @@
+/*
+ * regex_get_replace.c
+ *
+ * Copyright (c) 2018-2022 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 <errno.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/directory.h>
+
+void parse_module_check_dir(char const *src,char const *dir)
+{
+    log_flow() ;
+
+    int r ;
+    size_t srclen = strlen(src) ;
+    size_t dirlen = strlen(dir) ;
+
+    char t[srclen + dirlen + 1] ;
+    auto_strings(t, src, dir) ;
+
+    r = scan_mode(t,S_IFDIR) ;
+    if (r < 0) {
+        errno = EEXIST ;
+        log_diesys(LOG_EXIT_ZERO, "conflicting format of: ", t) ;
+    }
+
+    if (!r)
+        if (!dir_create_parent(t, 0755))
+            log_dieusys(LOG_EXIT_ZERO, "create directory: ", t) ;
+}
diff --git a/src/lib66/module/regex_configure.c b/src/lib66/module/regex_configure.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b6a33b89a5033eeb4fa3a129f12fc3af1bc23fb
--- /dev/null
+++ b/src/lib66/module/regex_configure.c
@@ -0,0 +1,145 @@
+/*
+ * regex_configure.c
+ *
+ * Copyright (c) 2018-2022 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 <sys/types.h>
+#include <string.h>
+#include <pwd.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/sastr.h>
+#include <oblibs/environ.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/types.h>
+#include <skalibs/env.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/bytestr.h>
+
+#include <66/module.h>
+#include <66/resolve.h>
+#include <66/info.h>
+#include <66/environ.h>
+#include <66/write.h>
+
+void regex_configure(resolve_service_t *res, ssexec_t *info, char const *path, char const *name)
+{
+    log_flow() ;
+
+    int wstat, r ;
+    pid_t pid ;
+    size_t clen = res->regex.configure > 0 ? 1 : 0 ;
+    size_t pathlen = strlen(path), n ;
+
+    stralloc env = STRALLOC_ZERO ;
+
+    char const *newargv[2 + clen] ;
+    unsigned int m = 0 ;
+
+    char pwd[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1] ;
+    auto_strings(pwd, path, "/", SS_MODULE_CONFIG_DIR + 1) ;
+
+    char config_script[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1 + SS_MODULE_CONFIG_SCRIPT_LEN + 1] ;
+    auto_strings(config_script, path, "/", SS_MODULE_CONFIG_DIR + 1, "/", SS_MODULE_CONFIG_SCRIPT) ;
+
+    r = scan_mode(config_script, S_IFREG) ;
+    if (r > 0)
+    {
+        /** export ssexec_t info value on the environment */
+        {
+            char verbo[UINT_FMT];
+            verbo[uid_fmt(verbo, VERBOSITY)] = 0 ;
+            if (!auto_stra(&env, \
+            "MOD_NAME=", name, "\n", \
+            "MOD_BASE=", res->sa.s + res->path.home, "\n", \
+            "MOD_LIVE=", info->live.s, "\n", \
+            "MOD_SCANDIR=", info->scandir.s, "\n", \
+            "MOD_TREENAME=", res->sa.s + res->treename, "\n", \
+            "MOD_OWNER=", res->sa.s + res->ownerstr, "\n", \
+            "MOD_COLOR=", info->opt_color ? "1" : "0", "\n", \
+            "MOD_VERBOSITY=", verbo, "\n", \
+            "MOD_MODULE_DIR=", path, "\n", \
+            "MOD_SKEL_DIR=", SS_SKEL_DIR, "\n", \
+            "MOD_SERVICE_SYSDIR=", SS_SERVICE_SYSDIR, "\n", \
+            "MOD_SERVICE_ADMDIR=", SS_SERVICE_ADMDIR, "\n", \
+            "MOD_SERVICE_ADMCONFDIR=", SS_SERVICE_ADMCONFDIR, "\n", \
+            "MOD_MODULE_SYSDIR=", SS_MODULE_SYSDIR, "\n", \
+            "MOD_MODULE_ADMDIR=", SS_MODULE_ADMDIR, "\n", \
+            "MOD_SCRIPT_SYSDIR=", SS_SCRIPT_SYSDIR, "\n", \
+            "MOD_USER_DIR=", SS_USER_DIR, "\n", \
+            "MOD_SERVICE_USERDIR=", SS_SERVICE_USERDIR, "\n", \
+            "MOD_SERVICE_USERCONFDIR=", SS_SERVICE_USERCONFDIR, "\n", \
+            "MOD_MODULE_USERDIR=", SS_MODULE_USERDIR, "\n", \
+            "MOD_SCRIPT_USERDIR=", SS_SCRIPT_USERDIR, "\n"))
+                log_dieu(LOG_EXIT_SYS, "append environment variables") ;
+        }
+
+        /** environment is not mandatory */
+        if (res->environ.env > 0)
+        {
+            stralloc oenv = STRALLOC_ZERO ;
+            stralloc dst = STRALLOC_ZERO ;
+            char name[strlen(res->sa.s + res->name) + 2] ;
+            auto_strings(name, ".", res->sa.s + res->name) ;
+
+            if (!env_prepare_for_write(&dst, &oenv, res))
+                log_dieu(LOG_EXIT_SYS, "prepare environment") ;
+
+            write_environ(name, oenv.s, dst.s) ;
+
+            /** Reads all files from the directory */
+            if (!environ_clean_envfile(&env, dst.s))
+                log_dieu(LOG_EXIT_SYS, "read environment") ;
+
+            if (!environ_remove_unexport(&env, &env))
+                log_dieu(LOG_EXIT_SYS, "remove exclamation mark from environment variables") ;
+
+            stralloc_free(&oenv) ;
+            stralloc_free(&dst) ;
+        }
+
+        if (!sastr_split_string_in_nline(&env))
+            log_dieu(LOG_EXIT_SYS, "rebuild environment") ;
+
+        n = env_len((const char *const *)environ) + 1 + byte_count(env.s,env.len,'\0') ;
+        char const *newenv[n + 1] ;
+
+        if (!env_merge (newenv, n ,(const char *const *)environ,env_len((const char *const *)environ), env.s, env.len))
+            log_dieu(LOG_EXIT_SYS, "build environment") ;
+
+        if (chdir(pwd) < 0)
+            log_dieu(LOG_EXIT_SYS, "chdir to: ", pwd) ;
+
+        m = 0 ;
+        newargv[m++] = config_script ;
+
+        if (res->regex.configure > 0)
+            newargv[m++] = res->sa.s + res->regex.configure ;
+
+        newargv[m++] = 0 ;
+
+        log_info("launch script configure of module: ", name) ;
+
+        pid = child_spawn0(newargv[0], newargv, newenv) ;
+
+        if (waitpid_nointr(pid, &wstat, 0) < 0)
+            log_dieusys(LOG_EXIT_SYS, "wait for: ", config_script) ;
+
+        if (wstat)
+            log_dieu(LOG_EXIT_SYS, "run: ", config_script) ;
+    }
+
+    stralloc_free(&env) ;
+}
diff --git a/src/lib66/module/regex_get_file_name.c b/src/lib66/module/regex_get_file_name.c
new file mode 100644
index 0000000000000000000000000000000000000000..b97fab05dabcf69d9faf5212fab2a7ec42b33553
--- /dev/null
+++ b/src/lib66/module/regex_get_file_name.c
@@ -0,0 +1,48 @@
+/*
+ * regex_get_file_name.c
+ *
+ * Copyright (c) 2018-2022 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/mill.h>
+
+#include <skalibs/stralloc.h>
+
+/* 0 filename undefine
+ * -1 system error
+ * should return at least 2 meaning :: no file define*/
+int regex_get_file_name(char *filename, char const *str)
+{
+    log_flow() ;
+
+    int r ;
+    size_t pos = 0 ;
+    stralloc kp = STRALLOC_ZERO ;
+
+    parse_mill_t MILL_GET_COLON = {
+    .open = ':', .close = ':',
+    .skip = " \t\r", .skiplen = 3,
+    .forceclose = 1,
+    .inner.debug = "get_colon" } ;
+
+    r = mill_element(&kp, str, &MILL_GET_COLON, &pos) ;
+    if (r == -1)
+        log_dieu(LOG_EXIT_SYS, "get filename of line: ", str) ;
+
+    auto_strings(filename, kp.s) ;
+
+    stralloc_free(&kp) ;
+    return pos ;
+}
diff --git a/src/lib66/module/regex_get_regex.c b/src/lib66/module/regex_get_regex.c
new file mode 100644
index 0000000000000000000000000000000000000000..717d51e408d3065b5fd8f0496c2c244cfe7c60a3
--- /dev/null
+++ b/src/lib66/module/regex_get_regex.c
@@ -0,0 +1,33 @@
+/*
+ * regex_get_regex.c
+ *
+ * Copyright (c) 2018-2022 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 <oblibs/log.h>
+#include <oblibs/string.h>
+
+void regex_get_regex(char *regex, char const *str)
+{
+    log_flow() ;
+
+    size_t len = strlen(str) ;
+    int pos = get_len_until(str,'=') ;
+    if (!pos || pos == -1)
+        log_dieu(LOG_EXIT_SYS, "get regex string of line: ", str) ;
+    pos++ ; // remove '='
+    char tmp[len + 1] ;
+    memcpy(tmp,str + pos,len-pos) ;
+    tmp[len-pos] = 0 ;
+    auto_strings(regex,tmp) ;
+}
diff --git a/src/lib66/module/regex_get_replace.c b/src/lib66/module/regex_get_replace.c
new file mode 100644
index 0000000000000000000000000000000000000000..61ef2817a63514509a2f049e9931e144fd3f94db
--- /dev/null
+++ b/src/lib66/module/regex_get_replace.c
@@ -0,0 +1,31 @@
+/*
+ * regex_get_replace.c
+ *
+ * Copyright (c) 2018-2022 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 <oblibs/log.h>
+#include <oblibs/string.h>
+
+void regex_get_replace(char *replace, char const *str)
+{
+    log_flow() ;
+
+    int pos = get_len_until(str,'=') ;
+    if (!pos || pos == -1)
+       log_dieu(LOG_EXIT_SYS,"replace string of line: ", str) ;
+    char tmp[pos + 1] ;
+    memcpy(tmp,str,pos) ;
+    tmp[pos] = 0 ;
+    auto_strings(replace, tmp) ;
+}
diff --git a/src/lib66/module/regex_rename.c b/src/lib66/module/regex_rename.c
new file mode 100644
index 0000000000000000000000000000000000000000..0fcce188f9f7c6831a24b3a3dc77128c4b12c78f
--- /dev/null
+++ b/src/lib66/module/regex_rename.c
@@ -0,0 +1,94 @@
+/*
+ * regex_rename.c
+ *
+ * Copyright (c) 2018-2022 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 <unistd.h>
+#include <stdio.h>
+
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+
+#include <66/module.h>
+#include <66/constants.h>
+
+void regex_rename(stralloc *list, resolve_service_t *res, uint32_t element)
+{
+    log_flow() ;
+
+    stralloc sa = STRALLOC_ZERO ;
+
+    if (!element)
+        return ;
+
+    if (!sastr_clean_string(&sa, res->sa.s + element))
+        log_dieu(LOG_EXIT_SYS, "clean string") ;
+
+    size_t pos = 0, idx = 0, salen = sa.len ;
+    char t[sa.len] ;
+
+    sastr_to_char(t, &sa) ;
+
+    for (; pos < salen ; pos += strlen(t + pos) + 1) {
+
+        idx = 0 ;
+        char *line = t + pos ;
+        char replace[SS_MAX_PATH] = { 0 } ;
+        char regex[SS_MAX_PATH] = { 0 } ;
+
+        regex_get_replace(replace,line) ;
+
+        regex_get_regex(regex,line) ;
+
+        FOREACH_SASTR(list, idx) {
+
+            sa.len = 0 ;
+            char *str = list->s + idx ;
+            size_t len = strlen(str) ;
+            char dname[len + 1] ;
+
+            if (!ob_dirname(dname, str))
+                log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ;
+
+            if (!sabasename(&sa, str, len))
+                log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ;
+
+            if (!stralloc_0(&sa))
+                log_die_nomem("stralloc") ;
+
+            if (!sastr_replace(&sa, replace, regex))
+                log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ;
+
+            if (!stralloc_0(&sa))
+                log_die_nomem("stralloc") ;
+
+            char new[len + sa.len + 1] ;
+            auto_strings(new, dname, sa.s) ;
+
+            /** do not try to rename the same directory */
+            if (strcmp(str, new)) {
+
+                log_trace("rename: ", str, " to: ", new) ;
+                if (rename(str, new) == -1)
+                    //log_warnusys( "rename: ", str, " to: ", new) ;
+                    log_dieusys(LOG_EXIT_SYS, "rename: ", str, " to: ", new) ;
+
+                break ;
+            }
+        }
+    }
+    stralloc_free(&sa) ;
+}
diff --git a/src/lib66/module/regex_replace.c b/src/lib66/module/regex_replace.c
new file mode 100644
index 0000000000000000000000000000000000000000..d6ce2762583999391e634ca75b26fd308b211219
--- /dev/null
+++ b/src/lib66/module/regex_replace.c
@@ -0,0 +1,111 @@
+/*
+ * regex_replace.c
+ *
+ * Copyright (c) 2018-2022 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 <oblibs/log.h>
+#include <oblibs/sastr.h>
+#include <oblibs/files.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/resolve.h>
+#include <66/utils.h>
+#include <66/constants.h>
+#include <66/module.h>
+
+void regex_replace(stralloc *list, resolve_service_t *res)
+{
+    log_flow() ;
+
+    int r ;
+    size_t pos = 0, idx = 0 ;
+
+    stralloc frontend = STRALLOC_ZERO ;
+    stralloc sa = STRALLOC_ZERO ;
+
+    if (!res->regex.ninfiles)
+        return ;
+
+    if (!sastr_clean_string(&sa, res->sa.s + res->regex.infiles))
+        log_dieu(LOG_EXIT_SYS, "clean string") ;
+
+    FOREACH_SASTR(list, pos) {
+
+        frontend.len = idx = 0 ;
+        char *str = list->s + pos ;
+        size_t len = strlen(str) ;
+        char bname[len + 1] ;
+        char dname[len + 1] ;
+
+        if (!ob_basename(bname, str))
+            log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ;
+
+        if (!ob_dirname(dname, str))
+            log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ;
+
+        //log_trace("read service file of: ", dname, bname) ;
+        r = read_svfile(&frontend, bname, dname) ;
+        if (!r)
+            log_dieusys(LOG_EXIT_SYS, "read file: ", str) ;
+        else if (r == -1)
+            continue ;
+
+        {
+            FOREACH_SASTR(&sa, idx) {
+
+                int all = 0, fpos = 0 ;
+                char const *line = sa.s + idx ;
+                size_t linelen = strlen(line) ;
+                char filename[SS_MAX_SERVICE_NAME + 1] ;
+                char replace[linelen + 1] ;
+                char regex[linelen + 1] ;
+
+                if (linelen >= SS_MAX_PATH_LEN)
+                    log_die(LOG_EXIT_SYS, "limit exceeded in service: ", res->sa.s + res->name) ;
+
+                if ((line[0] != ':') || (get_sep_before(line + 1, ':', '=') < 0))
+                    log_die(LOG_EXIT_SYS, "bad format in line: ", line, " of key @infiles field") ;
+
+                memset(filename, 0, SS_MAX_SERVICE_NAME + 1) ;
+                memset(replace, 0, linelen + 1) ;
+                memset(regex, 0, linelen + 1) ;
+
+                fpos = regex_get_file_name(filename, line) ;
+                if (fpos < 3) all = 1 ;
+
+                regex_get_replace(replace, line + fpos) ;
+
+                regex_get_regex(regex, line + fpos) ;
+
+                if (!strcmp(bname, filename) || all) {
+
+                    if (!sastr_replace_all(&frontend, replace, regex))
+                        log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ;
+
+                    if (!stralloc_0(&frontend))
+                        log_dieusys(LOG_EXIT_SYS, "stralloc") ;
+
+                    frontend.len-- ;
+
+                    if (!file_write_unsafe(dname, bname, frontend.s, frontend.len))
+                        log_dieusys(LOG_EXIT_SYS, "write: ", dname, "/", bname) ;
+                }
+            }
+        }
+    }
+
+    stralloc_free(&frontend) ;
+    stralloc_free(&sa) ;
+}
diff --git a/src/lib66/parse/deps-lib/deps b/src/lib66/parse/deps-lib/deps
index 0313af57d79c8f2a9d1c3a112f57a061cabbdfdd..d6d430e87c1b4cef5d4ee1c996d774eec41a245f 100644
--- a/src/lib66/parse/deps-lib/deps
+++ b/src/lib66/parse/deps-lib/deps
@@ -10,7 +10,6 @@ parse_error.o
 parse_frontend.o
 parse_line_g.o
 parse_mandatory.o
-parse_module.o
 parse_parentheses.o
 parse_section.o
 parse_service.o
diff --git a/src/lib66/parse/parse_module.c b/src/lib66/parse/parse_module.c
deleted file mode 100644
index 9b871e68328b027565f584a3b2defbd44eb87478..0000000000000000000000000000000000000000
--- a/src/lib66/parse/parse_module.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * parse_module.c
- *
- * Copyright (c) 2018-2022 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 <errno.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <unistd.h> //chdir, unlink
-#include <stdlib.h>
-#include <stdio.h> //rename
-
-#include <oblibs/string.h>
-#include <oblibs/log.h>
-#include <oblibs/mill.h>
-#include <oblibs/sastr.h>
-#include <oblibs/types.h>
-#include <oblibs/directory.h>
-#include <oblibs/environ.h>
-#include <oblibs/files.h>
-
-#include <skalibs/stralloc.h>
-#include <skalibs/djbunix.h> //hiercopy
-#include <skalibs/env.h> //hiercopy
-#include <skalibs/bytestr.h>
-
-#include <66/write.h>
-#include <66/utils.h>
-#include <66/environ.h>
-#include <66/resolve.h>
-#include <66/service.h>
-#include <66/constants.h>
-#include <66/utils.h>
-
-#define SS_MODULE_CONFIG_DIR "/configure"
-#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)
-
-static void instance_splitname_to_char(char *store, char const *name, int len, int what)
-{
-    log_flow() ;
-
-    char const *copy ;
-    size_t tlen = len + 1, clen = 0 ;
-
-    char template[tlen + 1] ;
-    memcpy(template,name,tlen) ;
-    template[tlen] = 0 ;
-
-    copy = name + tlen ;
-
-    if (!what) {
-
-        auto_strings(store, template) ;
-
-    } else {
-
-        clen = strlen(copy) ;
-        memcpy(store, copy, clen) ;
-        store[clen] = 0 ;
-    }
-
-}
-
-static void parse_module_check_dir(char const *src,char const *dir)
-{
-    log_flow() ;
-
-    int r ;
-    size_t srclen = strlen(src) ;
-    size_t dirlen = strlen(dir) ;
-
-    char t[srclen + dirlen + 1] ;
-    auto_strings(t, src, dir) ;
-
-    r = scan_mode(t,S_IFDIR) ;
-    if (r < 0) {
-        errno = EEXIST ;
-        log_diesys(LOG_EXIT_ZERO, "conflicting format of: ", t) ;
-    }
-
-    if (!r)
-        if (!dir_create_parent(t, 0755))
-            log_dieusys(LOG_EXIT_ZERO, "create directory: ", t) ;
-}
-
-static void parse_module_check_name(char const *src, char const *name)
-{
-    log_flow() ;
-
-    char basename[strlen(src)] ;
-    int insta = -1 ;
-
-    if (!ob_basename(basename, src))
-        log_dieu(LOG_EXIT_SYS, "get basename of: ", src) ;
-
-    insta = instance_check(name) ;
-
-    if (insta <= 0)
-        log_die(LOG_EXIT_SYS, "invalid module instance name: ", name) ;
-
-    if (basename[0] != '@')
-        log_die(LOG_EXIT_USER, "invalid directory name for module: ", name, " -- directory name must start with a '@' character") ;
-}
-
-/* 0 filename undefine
- * -1 system error
- * should return at least 2 meaning :: no file define*/
-static int regex_get_file_name(char *filename, char const *str)
-{
-    log_flow() ;
-
-    int r ;
-    size_t pos = 0 ;
-    stralloc kp = STRALLOC_ZERO ;
-
-    parse_mill_t MILL_GET_COLON = {
-    .open = ':', .close = ':',
-    .skip = " \t\r", .skiplen = 3,
-    .forceclose = 1,
-    .inner.debug = "get_colon" } ;
-
-    r = mill_element(&kp, str, &MILL_GET_COLON, &pos) ;
-    if (r == -1)
-        log_dieu(LOG_EXIT_SYS, "get filename of line: ", str) ;
-
-    auto_strings(filename, kp.s) ;
-
-    stralloc_free(&kp) ;
-    return pos ;
-}
-
-static void regex_get_replace(char *replace, char const *str)
-{
-    log_flow() ;
-
-    int pos = get_len_until(str,'=') ;
-    if (!pos || pos == -1)
-       log_dieu(LOG_EXIT_SYS,"replace string of line: ", str) ;
-    char tmp[pos + 1] ;
-    memcpy(tmp,str,pos) ;
-    tmp[pos] = 0 ;
-    auto_strings(replace, tmp) ;
-}
-
-static void regex_get_regex(char *regex, char const *str)
-{
-    log_flow() ;
-
-    size_t len = strlen(str) ;
-    int pos = get_len_until(str,'=') ;
-    if (!pos || pos == -1)
-        log_dieu(LOG_EXIT_SYS, "get regex string of line: ", str) ;
-    pos++ ; // remove '='
-    char tmp[len + 1] ;
-    memcpy(tmp,str + pos,len-pos) ;
-    tmp[len-pos] = 0 ;
-    auto_strings(regex,tmp) ;
-}
-
-static void get_list(stralloc *list, char const *src, char const *name, mode_t mode)
-{
-    log_flow() ;
-
-    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))
-        log_dieusys(LOG_EXIT_SYS,"get file(s) of module: ", name) ;
-
-}
-
-static void regex_replace(stralloc *list, resolve_service_t *res)
-{
-    log_flow() ;
-
-    int r ;
-    size_t pos = 0, idx = 0 ;
-
-    stralloc frontend = STRALLOC_ZERO ;
-    stralloc sa = STRALLOC_ZERO ;
-
-    if (!res->regex.ninfiles)
-        return ;
-
-    if (!sastr_clean_string(&sa, res->sa.s + res->regex.infiles))
-        log_dieu(LOG_EXIT_SYS, "clean string") ;
-
-    FOREACH_SASTR(list, pos) {
-
-        frontend.len = idx = 0 ;
-        char *str = list->s + pos ;
-        size_t len = strlen(str) ;
-        char bname[len + 1] ;
-        char dname[len + 1] ;
-
-        if (!ob_basename(bname, str))
-            log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ;
-
-        if (!ob_dirname(dname, str))
-            log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ;
-
-        //log_trace("read service file of: ", dname, bname) ;
-        r = read_svfile(&frontend, bname, dname) ;
-        if (!r)
-            log_dieusys(LOG_EXIT_SYS, "read file: ", str) ;
-        else if (r == -1)
-            continue ;
-
-        {
-            FOREACH_SASTR(&sa, idx) {
-
-                int all = 0, fpos = 0 ;
-                char const *line = sa.s + idx ;
-                size_t linelen = strlen(line) ;
-                char filename[SS_MAX_SERVICE_NAME + 1] ;
-                char replace[linelen + 1] ;
-                char regex[linelen + 1] ;
-
-                if (linelen >= SS_MAX_PATH_LEN)
-                    log_die(LOG_EXIT_SYS, "limit exceeded in service: ", res->sa.s + res->name) ;
-
-                if ((line[0] != ':') || (get_sep_before(line + 1, ':', '=') < 0))
-                    log_die(LOG_EXIT_SYS, "bad format in line: ", line, " of key @infiles field") ;
-
-                memset(filename, 0, SS_MAX_SERVICE_NAME + 1) ;
-                memset(replace, 0, linelen + 1) ;
-                memset(regex, 0, linelen + 1) ;
-
-                fpos = regex_get_file_name(filename, line) ;
-                if (fpos < 3) all = 1 ;
-
-                regex_get_replace(replace, line + fpos) ;
-
-                regex_get_regex(regex, line + fpos) ;
-
-                if (!strcmp(bname, filename) || all) {
-
-                    if (!sastr_replace_all(&frontend, replace, regex))
-                        log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ;
-
-                    if (!stralloc_0(&frontend))
-                        log_dieusys(LOG_EXIT_SYS, "stralloc") ;
-
-                    frontend.len-- ;
-
-                    if (!file_write_unsafe(dname, bname, frontend.s, frontend.len))
-                        log_dieusys(LOG_EXIT_SYS, "write: ", dname, "/", bname) ;
-                }
-            }
-        }
-    }
-
-    stralloc_free(&frontend) ;
-    stralloc_free(&sa) ;
-}
-
-static void regex_rename(stralloc *list, resolve_service_t *res, uint32_t element)
-{
-    log_flow() ;
-
-    stralloc sa = STRALLOC_ZERO ;
-
-    if (!element)
-        return ;
-
-    if (!sastr_clean_string(&sa, res->sa.s + element))
-        log_dieu(LOG_EXIT_SYS, "clean string") ;
-
-    size_t pos = 0, idx = 0, salen = sa.len ;
-    char t[sa.len] ;
-
-    sastr_to_char(t, &sa) ;
-
-    for (; pos < salen ; pos += strlen(t + pos) + 1) {
-
-        idx = 0 ;
-        char *line = t + pos ;
-        char replace[SS_MAX_PATH] = { 0 } ;
-        char regex[SS_MAX_PATH] = { 0 } ;
-
-        regex_get_replace(replace,line) ;
-
-        regex_get_regex(regex,line) ;
-
-        FOREACH_SASTR(list, idx) {
-
-            sa.len = 0 ;
-            char *str = list->s + idx ;
-            size_t len = strlen(str) ;
-            char dname[len + 1] ;
-
-            if (!ob_dirname(dname, str))
-                log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ;
-
-            if (!sabasename(&sa, str, len))
-                log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ;
-
-            if (!stralloc_0(&sa))
-                log_die_nomem("stralloc") ;
-
-            if (!sastr_replace(&sa, replace, regex))
-                log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ;
-
-            if (!stralloc_0(&sa))
-                log_die_nomem("stralloc") ;
-
-            char new[len + sa.len + 1] ;
-            auto_strings(new, dname, sa.s) ;
-
-            /** do not try to rename the same directory */
-            if (strcmp(str, new)) {
-
-                log_trace("rename: ", str, " to: ", new) ;
-                if (rename(str, new) == -1)
-                    //log_warnusys( "rename: ", str, " to: ", new) ;
-                    log_dieusys(LOG_EXIT_SYS, "rename: ", str, " to: ", new) ;
-
-                break ;
-            }
-        }
-    }
-    stralloc_free(&sa) ;
-}
-
-static void regex_configure(resolve_service_t *res, ssexec_t *info, char const *path, char const *name)
-{
-    log_flow() ;
-
-    int wstat, r ;
-    pid_t pid ;
-    size_t clen = res->regex.configure > 0 ? 1 : 0 ;
-    size_t pathlen = strlen(path), n ;
-
-    stralloc env = STRALLOC_ZERO ;
-
-    char const *newargv[2 + clen] ;
-    unsigned int m = 0 ;
-
-    char pwd[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1] ;
-    auto_strings(pwd, path, "/", SS_MODULE_CONFIG_DIR + 1) ;
-
-    char config_script[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1 + SS_MODULE_CONFIG_SCRIPT_LEN + 1] ;
-    auto_strings(config_script, path, "/", SS_MODULE_CONFIG_DIR + 1, "/", SS_MODULE_CONFIG_SCRIPT) ;
-
-    r = scan_mode(config_script, S_IFREG) ;
-    if (r > 0)
-    {
-        /** export ssexec_t info value on the environment */
-        {
-            char verbo[UINT_FMT];
-            verbo[uid_fmt(verbo, VERBOSITY)] = 0 ;
-            if (!auto_stra(&env, \
-            "MOD_NAME=", name, "\n", \
-            "MOD_BASE=", res->sa.s + res->path.home, "\n", \
-            "MOD_LIVE=", res->sa.s + res->live.livedir, "\n", \
-            "MOD_SCANDIR=", res->sa.s + res->live.scandir, "\n", \
-            "MOD_TREENAME=", res->sa.s + res->treename, "\n", \
-            "MOD_OWNER=", res->sa.s + res->ownerstr, "\n", \
-            "MOD_COLOR=", info->opt_color ? "1" : "0", "\n", \
-            "MOD_VERBOSITY=", verbo, "\n", \
-            "MOD_MODULE_DIR=", path, "\n", \
-            "MOD_SKEL_DIR=", SS_SKEL_DIR, "\n", \
-            "MOD_SERVICE_SYSDIR=", SS_SERVICE_SYSDIR, "\n", \
-            "MOD_SERVICE_ADMDIR=", SS_SERVICE_ADMDIR, "\n", \
-            "MOD_SERVICE_ADMCONFDIR=", SS_SERVICE_ADMCONFDIR, "\n", \
-            "MOD_MODULE_SYSDIR=", SS_MODULE_SYSDIR, "\n", \
-            "MOD_MODULE_ADMDIR=", SS_MODULE_ADMDIR, "\n", \
-            "MOD_SCRIPT_SYSDIR=", SS_SCRIPT_SYSDIR, "\n", \
-            "MOD_USER_DIR=", SS_USER_DIR, "\n", \
-            "MOD_SERVICE_USERDIR=", SS_SERVICE_USERDIR, "\n", \
-            "MOD_SERVICE_USERCONFDIR=", SS_SERVICE_USERCONFDIR, "\n", \
-            "MOD_MODULE_USERDIR=", SS_MODULE_USERDIR, "\n", \
-            "MOD_SCRIPT_USERDIR=", SS_SCRIPT_USERDIR, "\n"))
-                log_dieu(LOG_EXIT_SYS, "append environment variables") ;
-        }
-
-        /** environment is not mandatory */
-        if (res->environ.env > 0)
-        {
-            stralloc oenv = STRALLOC_ZERO ;
-            stralloc dst = STRALLOC_ZERO ;
-            char name[strlen(res->sa.s + res->name) + 2] ;
-            auto_strings(name, ".", res->sa.s + res->name) ;
-
-            if (!env_prepare_for_write(&dst, &oenv, res))
-                log_dieu(LOG_EXIT_SYS, "prepare environment") ;
-
-            write_environ(name, oenv.s, dst.s) ;
-
-            /** Reads all files from the directory */
-            if (!environ_clean_envfile(&env, dst.s))
-                log_dieu(LOG_EXIT_SYS, "read environment") ;
-
-            if (!environ_remove_unexport(&env, &env))
-                log_dieu(LOG_EXIT_SYS, "remove exclamation mark from environment variables") ;
-
-            stralloc_free(&oenv) ;
-            stralloc_free(&dst) ;
-        }
-
-        if (!sastr_split_string_in_nline(&env))
-            log_dieu(LOG_EXIT_SYS, "rebuild environment") ;
-
-        n = env_len((const char *const *)environ) + 1 + byte_count(env.s,env.len,'\0') ;
-        char const *newenv[n + 1] ;
-
-        if (!env_merge (newenv, n ,(const char *const *)environ,env_len((const char *const *)environ), env.s, env.len))
-            log_dieu(LOG_EXIT_SYS, "build environment") ;
-
-        if (chdir(pwd) < 0)
-            log_dieu(LOG_EXIT_SYS, "chdir to: ", pwd) ;
-
-        m = 0 ;
-        newargv[m++] = config_script ;
-
-        if (res->regex.configure > 0)
-            newargv[m++] = res->sa.s + res->regex.configure ;
-
-        newargv[m++] = 0 ;
-
-        log_info("launch script configure of module: ", name) ;
-
-        pid = child_spawn0(newargv[0], newargv, newenv) ;
-
-        if (waitpid_nointr(pid, &wstat, 0) < 0)
-            log_dieusys(LOG_EXIT_SYS, "wait for: ", config_script) ;
-
-        if (wstat)
-            log_dieu(LOG_EXIT_SYS, "run: ", config_script) ;
-    }
-
-    stralloc_free(&env) ;
-}
-
-void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force)
-{
-    log_flow() ;
-
-    int r, insta = -1 ;
-    unsigned int residx = 0 ;
-    size_t pos = 0, pathlen = 0 ;
-    char *name = res->sa.s + res->name ;
-    char *src = res->sa.s + res->path.frontend ;
-    char path[SS_MAX_PATH_LEN] ;
-    char ainsta[strlen(name)] ;
-    stralloc list = STRALLOC_ZERO ;
-    resolve_wrapper_t_ref wres = 0 ;
-
-    log_trace("parse module: ", name) ;
-
-    insta = instance_check(name) ;
-    instance_splitname_to_char(ainsta, name, insta, 0) ;
-
-    size_t prefixlen = strlen(ainsta) ;
-    size_t len = prefixlen + SS_MAX_SERVICE_NAME ;
-
-    char prefix[len + 1] ;
-    auto_strings(prefix, ainsta) ;
-    //prefix[insta] = '-' ;
-    prefix[insta] = 0 ;
-
-    if (!getuid()) {
-
-        auto_strings(path, SS_SERVICE_ADMDIR, name) ;
-
-    } else {
-
-        if (!set_ownerhome_stack(path))
-            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) ;
-    }
-
-    uint8_t conf = res->environ.env_overwrite ;
-
-    /** Check the validity of the module directory.
-     * The frontend file of the module must be located in
-     * a directory with a name in the format @template_name:
-     *      - frontend file -> scandir@
-     *      - directory name containing the frontend service file -> @scandir */
-    parse_module_check_name(src, name) ;
-
-    /** check mandatory directories
-     * res->frontend/module_name/{configure,service,service@} */
-    parse_module_check_dir(src, SS_MODULE_CONFIG_DIR) ;
-    parse_module_check_dir(src, SS_MODULE_SERVICE) ;
-    parse_module_check_dir(src, SS_MODULE_SERVICE_INSTANCE) ;
-
-    r = scan_mode(path, S_IFDIR) ;
-    if (r == -1) {
-        errno = EEXIST ;
-        log_dieusys(LOG_EXIT_SYS, "conflicting format of: ", path) ;
-
-    } else if (!r) {
-
-        if (!hiercopy(src, path))
-            log_dieusys(LOG_EXIT_SYS, "copy: ", src, " to: ", path) ;
-
-    } else {
-
-        /** Must reconfigure all services of the module */
-        if (force < 2) {
-
-            log_warn("skip configuration of the module: ", name, " -- already configured") ;
-            goto deps ;
-        }
-
-        if (rm_rf(path) < 0)
-            log_dieusys (LOG_EXIT_SYS, "remove: ", path) ;
-
-        if (!hiercopy(src, path))
-            log_dieusys(LOG_EXIT_SYS,"copy: ", src, " to: ", path) ;
-    }
-
-    pathlen = strlen(path) ;
-    /** 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) ;
-
-    if (unlink(path) < 0)
-        log_dieusys(LOG_EXIT_ZERO, "unlink: ", path) ;
-
-    path[pathlen] = 0 ;
-
-    /** contents */
-    get_list(&list, path, name, S_IFREG) ;
-    regex_replace(&list, res) ;
-
-    /** directories */
-    get_list(&list, path, name, S_IFDIR) ;
-    regex_rename(&list, res, res->regex.directories) ;
-
-    /** filename */
-    get_list(&list, path, name, S_IFREG) ;
-    regex_rename(&list, res, res->regex.files) ;
-
-    /** configure script */
-    regex_configure(res, info, path, name) ;
-
-    deps:
-
-    list.len = 0 ;
-
-    if (!auto_stra(&list, path))
-        log_die_nomem("stralloc") ;
-
-    char t[list.len] ;
-
-    sastr_to_char(t, &list) ;
-
-    list.len = 0 ;
-    char const *exclude[3] = { SS_MODULE_CONFIG_DIR + 1, SS_MODULE_SERVICE_INSTANCE + 1, 0 } ;
-    if (!sastr_dir_get_recursive(&list, t, exclude, S_IFREG, 1))
-        log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", name) ;
-
-    char l[list.len] ;
-    size_t llen = list.len ;
-
-    sastr_to_char(l, &list) ;
-
-    list.len = 0 ;
-
-    for (pos = 0 ; pos < llen ; pos += strlen(l + pos) + 1) {
-
-        char *dname = l + pos ;
-        char ainsta[pathlen + SS_MODULE_SERVICE_INSTANCE_LEN + 1 + SS_MAX_SERVICE_NAME + 1] ;
-        size_t namelen = strlen(dname) ;
-        char bname[namelen] ;
-
-        if (!ob_basename(bname,dname))
-            log_dieu(LOG_EXIT_SYS, "find basename of: ", dname) ;
-
-        if (instance_check(bname) > 0) {
-            auto_strings(ainsta, path, SS_MODULE_SERVICE_INSTANCE, "/", bname) ;
-            dname = ainsta ;
-        }
-
-        if (!sastr_add_string(&list, bname))
-            log_die_nomem("stralloc") ;
-
-        if (!strcmp(name, bname))
-            log_die(LOG_EXIT_SYS, "cyclic call detected -- ", name, " call ", bname) ;
-
-        /** nothing to do with the exit code */
-        parse_frontend(dname, ares, areslen, info, force, conf, &residx, path, bname) ;
-
-        wres = resolve_set_struct(DATA_SERVICE, &ares[residx]) ;
-
-        ares[residx].inmodule = resolve_add_string(wres, prefix - 1) ;
-    }
-
-    char deps[list.len] ;
-
-    sastr_to_char(deps, &list) ;
-
-    llen = list.len ;
-
-    list.len = 0 ;
-
-    /* rebuild the dependencies list incorporating the services defined inside
-     * the module. */
-
-    if (res->dependencies.ndepends)
-        if (!sastr_clean_string(&list, res->sa.s + res->dependencies.depends))
-            log_dieu(LOG_EXIT_SYS, "clean string") ;
-
-    for (pos = 0 ; pos < llen ; pos += strlen(deps + pos) + 1)
-        if (!sastr_add_string(&list, deps + pos))
-            log_die_nomem("stralloc") ;
-
-    wres = resolve_set_struct(DATA_SERVICE, res) ;
-
-    res->dependencies.depends = parse_compute_list(wres, &list, &res->dependencies.ndepends, 0) ;
-
-    free(wres) ;
-    stralloc_free(&list) ;
-}