]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
makefile nit and modstack.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Dec 2007 13:23:41 +0000 (13:23 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Dec 2007 13:23:41 +0000 (13:23 +0000)
git-svn-id: file:///svn/unbound/trunk@801 be551aaa-1e26-0410-a405-d3ace91eadb9

Makefile.in
daemon/daemon.c
daemon/daemon.h
daemon/worker.c
doc/Changelog
services/mesh.c
services/mesh.h
services/modstack.c [new file with mode: 0644]
services/modstack.h [new file with mode: 0644]

index 3d6ad04fab6f451dd7141954bc6ec353f0d20691..311446b75d98133a26f45b872d4164a7386688de 100644 (file)
@@ -138,7 +138,7 @@ unbound-checkconf:  $(CHECKCONF_OBJ) $(ldnslib)
        $(INFO) Link $@
        $Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
 
-unbound-host:  $(HOST_OBJ) lib
+unbound-host:  $(HOST_OBJ) libunbound.la
        $(INFO) Link $@
        $Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
 
index 43334d696da2a2fff3410998b919b555f780b1f7..12785135aa6a959eda914301b72d535a1e39969f 100644 (file)
 #include "services/cache/rrset.h"
 #include "services/cache/infra.h"
 #include "services/localzone.h"
+#include "services/modstack.h"
 #include "util/module.h"
-#include "iterator/iterator.h"
-#include "validator/validator.h"
-#include "util/fptr_wlist.h"
 #include <signal.h>
 
 /** How many quit requests happened. */
@@ -129,7 +127,7 @@ daemon_init()
        checklock_start();
        ERR_load_crypto_strings();
        daemon->need_to_exit = 0;
-       daemon->num_modules = 0;
+       modstack_init(&daemon->mods);
        if(!(daemon->env = (struct module_env*)calloc(1, 
                sizeof(*daemon->env)))) {
                free(daemon);
@@ -158,136 +156,19 @@ daemon_open_shared_ports(struct daemon* daemon)
        return 1;
 }
 
-/** count number of modules (words) in the string */
-static int
-count_modules(const char* s)
-{
-       int num = 0;
-       if(!s)
-               return 0;
-       while(*s) {
-               /* skip whitespace */
-               while(*s && isspace((int)*s))
-                       s++;
-               if(*s && !isspace((int)*s)) {
-                       /* skip identifier */
-                       num++;
-                       while(*s && !isspace((int)*s))
-                               s++;
-               }
-       }
-       return num;
-}
-
-/**
- * Get funcblock for module name
- * @param str: string with module name. Advanced to next value on success.
- * @return funcblock or NULL on error.
- */
-static struct module_func_block*
-daemon_module_factory(const char** str)
-{
-       /* these are the modules available */
-       int num = 2;
-       const char* names[] = {"iterator", "validator", NULL};
-       struct module_func_block* (*fb[])(void) = 
-               {&iter_get_funcblock, &val_get_funcblock, NULL};
-
-       int i;
-       const char* s = *str;
-       while(*s && isspace((int)*s))
-               s++;
-       for(i=0; i<num; i++) {
-               if(strncmp(names[i], s, strlen(names[i])) == 0) {
-                       s += strlen(names[i]);
-                       *str = s;
-                       return (*fb[i])();
-               }
-       }
-       return NULL;
-}
-
-/**
- * Read config file module settings and set up the modfunc block
- * @param daemon: the daemon.
- * @return false on error
- */
-static int
-daemon_config_modules(struct daemon* daemon)
-{
-       const char* str = daemon->cfg->module_conf;
-       int i;
-       verbose(VERB_DETAIL, "module config: \"%s\"", str);
-       daemon->num_modules = count_modules(str);
-       if(daemon->num_modules == 0) {
-               log_err("error: no modules specified");
-               return 0;
-       }
-       if(daemon->num_modules > MAX_MODULE) {
-               log_err("error: too many modules (%d max %d)",
-                       daemon->num_modules, MAX_MODULE);
-               return 0;
-       }
-       daemon->modfunc = (struct module_func_block**)calloc((size_t)
-               daemon->num_modules, sizeof(struct module_func_block*));
-       if(!daemon->modfunc) {
-               log_err("out of memory");
-               return 0;
-       }
-       for(i=0; i<daemon->num_modules; i++) {
-               daemon->modfunc[i] = daemon_module_factory(&str);
-               if(!daemon->modfunc[i]) {
-                       log_err("Unknown value for first module in: '%s'",
-                               str);
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-/**
- * Desetup the modules, deinit, delete.
- * @param daemon: the daemon.
- */
-static void
-daemon_desetup_modules(struct daemon* daemon)
-{
-       int i;
-       for(i=0; i<daemon->num_modules; i++) {
-               log_assert(fptr_whitelist_mod_deinit(
-                       daemon->modfunc[i]->deinit));
-               (*daemon->modfunc[i]->deinit)(daemon->env, i);
-       }
-       daemon->num_modules = 0;
-       free(daemon->modfunc);
-       daemon->modfunc = 0;
-}
-
 /**
- * Setup modules. Assigns ids and calls module_init.
+ * Setup modules. setup module stack.
  * @param daemon: the daemon
  */
 static void daemon_setup_modules(struct daemon* daemon)
 {
-       int i;
-       if(daemon->num_modules != 0)
-               daemon_desetup_modules(daemon);
-       /* fixed setup of the modules */
-       if(!daemon_config_modules(daemon)) {
-               fatal_exit("failed to setup modules");
-       }
        daemon->env->cfg = daemon->cfg;
        daemon->env->alloc = &daemon->superalloc;
        daemon->env->worker = NULL;
        daemon->env->need_to_validate = 0; /* set by module init below */
-       for(i=0; i<daemon->num_modules; i++) {
-               verbose(VERB_OPS, "init module %d: %s", 
-                       i, daemon->modfunc[i]->name);
-               log_assert(fptr_whitelist_mod_init(daemon->modfunc[i]->init));
-               if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
-                       fatal_exit("module init for module %s failed",
-                               daemon->modfunc[i]->name);
-               }
+       if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, 
+               daemon->env)) {
+               fatal_exit("failed to setup modules");
        }
 }
 
@@ -475,7 +356,7 @@ daemon_delete(struct daemon* daemon)
 {
        if(!daemon)
                return;
-       daemon_desetup_modules(daemon);
+       modstack_desetup(&daemon->mods, daemon->env);
        listening_ports_free(daemon->ports);
        if(daemon->env) {
                slabhash_delete(daemon->env->msg_cache);
index 37bc219b56b6ef30c17407cd839c3a9338f29dd1..d8db511cfdd27d26fe2918bace6015482d79410c 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "util/locks.h"
 #include "util/alloc.h"
+#include "services/modstack.h"
 struct config_file;
 struct worker;
 struct listen_port;
@@ -76,10 +77,8 @@ struct daemon {
        struct alloc_cache superalloc;
        /** the module environment master value, copied and changed by threads*/
        struct module_env* env;
-       /** number of modules active, ids from 0 to num-1. */
-       int num_modules;
-       /** the module callbacks, array of num_modules length */
-       struct module_func_block** modfunc;
+       /** stack of module callbacks */
+       struct module_stack mods;
        /** access control, which client IPs are allowed to connect */
        struct acl_list* acl;
        /** local authority zones */
index 977c111f031e0ff2ae3a96ef6fa5ff08ea78d742..6f6ee2ac6aa6917ddc057bd1f9d8b406c78ba132 100644 (file)
@@ -967,8 +967,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
        worker->env.alloc = &worker->alloc;
        worker->env.rnd = worker->rndstate;
        worker->env.scratch = worker->scratchpad;
-       worker->env.mesh = mesh_create(worker->daemon->num_modules,
-               worker->daemon->modfunc, &worker->env);
+       worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
        worker->env.detach_subs = &mesh_detach_subs;
        worker->env.attach_sub = &mesh_attach_sub;
        worker->env.kill_sub = &mesh_state_delete;
index bc983b7e81f68efca8329474e72dc387c738c471..dc4f349d79552e6186c27ef07435232be1e097fd 100644 (file)
@@ -1,3 +1,8 @@
+4 December 2007: Wouter
+       - minor Makefile fixup.
+       - moved module-stack code out of daemon/daemon into services/modstack,
+         preparing for code-reuse.
+
 3 December 2007: Wouter
        - changed checkconf/ to smallapp/ to make room for more support tools.
          (such as unbound-host).
index 22f951e8857054401f73b020bf43e97410430156..f8ae1161d286ab325670d27ed64ce71dddab56c3 100644 (file)
@@ -88,8 +88,7 @@ mesh_state_ref_compare(const void* ap, const void* bp)
 }
 
 struct mesh_area* 
-mesh_create(int num_modules, struct module_func_block** modfunc,
-       struct module_env* env)
+mesh_create(struct module_stack* stack, struct module_env* env)
 {
        struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
        if(!mesh) {
@@ -102,8 +101,7 @@ mesh_create(int num_modules, struct module_func_block** modfunc,
                log_err("mesh area alloc: out of memory");
                return NULL;
        }
-       mesh->num_modules = num_modules;
-       mesh->modfunc = modfunc;
+       mesh->mods = *stack;
        mesh->env = env;
        rbtree_init(&mesh->run, &mesh_state_compare);
        rbtree_init(&mesh->all, &mesh_state_compare);
@@ -237,7 +235,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
        mstate->s.env = env;
        mstate->s.mesh_info = mstate;
        /* init modules */
-       for(i=0; i<env->mesh->num_modules; i++) {
+       for(i=0; i<env->mesh->mods.num; i++) {
                mstate->s.minfo[i] = NULL;
                mstate->s.ext_state[i] = module_state_initial;
        }
@@ -253,9 +251,9 @@ mesh_state_cleanup(struct mesh_state* mstate)
                return;
        /* de-init modules */
        mesh = mstate->s.env->mesh;
-       for(i=0; i<mesh->num_modules; i++) {
-               log_assert(fptr_whitelist_mod_clear(mesh->modfunc[i]->clear));
-               (*mesh->modfunc[i]->clear)(&mstate->s, i);
+       for(i=0; i<mesh->mods.num; i++) {
+               log_assert(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
+               (*mesh->mods.mod[i]->clear)(&mstate->s, i);
                mstate->s.minfo[i] = NULL;
                mstate->s.ext_state[i] = module_finished;
        }
@@ -493,8 +491,8 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
                (void)rbtree_insert(&mesh->run, &ref->s->run_node);
                /* callback the function to inform super of result */
                log_assert(fptr_whitelist_mod_inform_super(
-                       mesh->modfunc[ref->s->s.curmod]->inform_super));
-               (*mesh->modfunc[ref->s->s.curmod]->inform_super)(&mstate->s, 
+                       mesh->mods.mod[ref->s->s.curmod]->inform_super));
+               (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s, 
                        ref->s->s.curmod, &ref->s->s);
        }
 }
@@ -565,7 +563,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
        if(s == module_wait_module) {
                /* start next module */
                mstate->s.curmod++;
-               if(mesh->num_modules == mstate->s.curmod) {
+               if(mesh->mods.num == mstate->s.curmod) {
                        log_err("Cannot pass to next module; at last module");
                        log_query_info(VERB_DETAIL, "pass error for qstate",
                                &mstate->s.qinfo);
@@ -602,8 +600,8 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
        while(mstate) {
                /* run the module */
                log_assert(fptr_whitelist_mod_operate(
-                       mesh->modfunc[mstate->s.curmod]->operate));
-               (*mesh->modfunc[mstate->s.curmod]->operate)
+                       mesh->mods.mod[mstate->s.curmod]->operate));
+               (*mesh->mods.mod[mstate->s.curmod]->operate)
                        (&mstate->s, ev, mstate->s.curmod, e);
 
                /* examine results */
@@ -611,7 +609,7 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
                regional_free_all(mstate->s.env->scratch);
                s = mstate->s.ext_state[mstate->s.curmod];
                verbose(VERB_ALGO, "mesh_run: %s module exit state is %s", 
-                       mesh->modfunc[mstate->s.curmod]->name, strextstate(s));
+                       mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
                e = NULL;
                if(mesh_continue(mesh, mstate, s, &ev))
                        continue;
index 57001ed471bd47f66c3bae0a1667767c28ad3849..7ba98732f3e30a495b0ef69fc238785a8c8924b4 100644 (file)
@@ -50,6 +50,7 @@
 #include "util/netevent.h"
 #include "util/data/msgparse.h"
 #include "util/module.h"
+#include "services/modstack.h"
 struct mesh_state;
 struct mesh_reply;
 struct query_info;
@@ -67,10 +68,8 @@ struct timehist;
  * Mesh of query states
  */
 struct mesh_area {
-       /** the number of modules */
-       int num_modules;
-       /** the module callbacks, array of num_modules length (ref only) */
-       struct module_func_block** modfunc;
+       /** active module stack */
+       struct module_stack mods;
        /** environment for new states */
        struct module_env* env;
 
@@ -160,14 +159,12 @@ struct mesh_reply {
 
 /**
  * Allocate mesh, to empty.
- * @param num_modules: number of modules that are present.
- * @param modfunc: array passed (alloced and deleted by caller), that has
- *     num_modules function callbacks for the modules.
+ * @param stack: module stack to activate, copied (as readonly reference).
  * @param env: environment for new queries.
  * @return mesh: the new mesh or NULL on error.
  */
-struct mesh_area* mesh_create(int num_modules
-       struct module_func_block** modfunc, struct module_env* env);
+struct mesh_area* mesh_create(struct module_stack* stack
+       struct module_env* env);
 
 /**
  * Delete mesh, and all query states and replies in it.
diff --git a/services/modstack.c b/services/modstack.c
new file mode 100644 (file)
index 0000000..0040c3d
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * services/modstack.c - stack of modules
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to help maintain a stack of modules.
+ */
+#include "config.h"
+#include "services/modstack.h"
+#include "util/module.h"
+#include "util/fptr_wlist.h"
+#include "iterator/iterator.h"
+#include "validator/validator.h"
+
+/** count number of modules (words) in the string */
+static int
+count_modules(const char* s)
+{
+        int num = 0;
+        if(!s)
+                return 0;
+        while(*s) {
+                /* skip whitespace */
+                while(*s && isspace((int)*s))
+                        s++;
+                if(*s && !isspace((int)*s)) {
+                        /* skip identifier */
+                        num++;
+                        while(*s && !isspace((int)*s))
+                                s++;
+                }
+        }
+        return num;
+}
+
+void 
+modstack_init(struct module_stack* stack)
+{
+       stack->num = 0;
+       stack->mod = NULL;
+}
+
+int 
+modstack_config(struct module_stack* stack, const char* module_conf)
+{
+        int i;
+        verbose(VERB_DETAIL, "module config: \"%s\"", module_conf);
+        stack->num = count_modules(module_conf);
+        if(stack->num == 0) {
+                log_err("error: no modules specified");
+                return 0;
+        }
+        if(stack->num > MAX_MODULE) {
+                log_err("error: too many modules (%d max %d)",
+                        stack->num, MAX_MODULE);
+                return 0;
+        }
+        stack->mod = (struct module_func_block**)calloc((size_t)
+                stack->num, sizeof(struct module_func_block*));
+        if(!stack->mod) {
+                log_err("out of memory");
+                return 0;
+        }
+        for(i=0; i<stack->num; i++) {
+                stack->mod[i] = module_factory(&module_conf);
+                if(!stack->mod[i]) {
+                        log_err("Unknown value for next module: '%s'",
+                                module_conf);
+                        return 0;
+                }
+        }
+        return 1;
+}
+
+struct 
+module_func_block* module_factory(const char** str)
+{
+        /* these are the modules available */
+        int num = 2;
+        const char* names[] = {"iterator", "validator", NULL};
+        struct module_func_block* (*fb[])(void) = 
+                {&iter_get_funcblock, &val_get_funcblock, NULL};
+
+        int i;
+        const char* s = *str;
+        while(*s && isspace((int)*s))
+                s++;
+        for(i=0; i<num; i++) {
+                if(strncmp(names[i], s, strlen(names[i])) == 0) {
+                        s += strlen(names[i]);
+                        *str = s;
+                        return (*fb[i])();
+                }
+        }
+        return NULL;
+}
+
+int 
+modstack_setup(struct module_stack* stack, const char* module_conf,
+       struct module_env* env)
+{
+        int i;
+        if(stack->num != 0)
+                modstack_desetup(stack, env);
+        /* fixed setup of the modules */
+        if(!modstack_config(stack, module_conf)) {
+               return 0;
+        }
+        env->need_to_validate = 0; /* set by module init below */
+        for(i=0; i<stack->num; i++) {
+                verbose(VERB_OPS, "init module %d: %s",
+                        i, stack->mod[i]->name);
+                log_assert(fptr_whitelist_mod_init(stack->mod[i]->init));
+                if(!(*stack->mod[i]->init)(env, i)) {
+                        log_err("module init for module %s failed",
+                                stack->mod[i]->name);
+                       return 0;
+                }
+        }
+       return 1;
+}
+
+void 
+modstack_desetup(struct module_stack* stack, struct module_env* env)
+{
+        int i;
+        for(i=0; i<stack->num; i++) {
+                log_assert(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
+                (*stack->mod[i]->deinit)(env, i);
+        }
+        stack->num = 0;
+        free(stack->mod);
+        stack->mod = NULL;
+}
diff --git a/services/modstack.h b/services/modstack.h
new file mode 100644 (file)
index 0000000..e76b465
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * services/modstack.h - stack of modules
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to help maintain a stack of modules.
+ */
+
+#ifndef SERVICES_MODSTACK_H
+#define SERVICES_MODSTACK_H
+struct module_func_block;
+struct module_env;
+
+/**
+ * Stack of modules.
+ */
+struct module_stack {
+       /** the number of modules */
+       int num;
+       /** the module callbacks, array of num_modules length (ref only) */
+       struct module_func_block** mod;
+};
+
+/**
+ * Init a stack of modules
+ * @param stack: initialised as empty.
+ */
+void modstack_init(struct module_stack* stack);
+
+/**
+ * Read config file module settings and set up the modfunc block
+ * @param stack: the stack of modules (empty before call). 
+ * @param module_conf: string what modules to insert.
+ * @return false on error
+ */
+int modstack_config(struct module_stack* stack, const char* module_conf);
+
+/**
+ * Get funcblock for module name
+ * @param str: string with module name. Advanced to next value on success.
+ *     The string is assumed whitespace separated list of module names.
+ * @return funcblock or NULL on error.
+ */
+struct module_func_block* module_factory(const char** str);
+
+/**
+ * Setup modules. Assigns ids and calls module_init.
+ * @param stack: if not empty beforehand, it will be desetup()ed.
+ *     It is then modstack_configged().
+ * @param module_conf: string what modules to insert.
+ * @param env: module environment which is inited by the modules.
+ *     environment should have a superalloc, cfg,
+ *     env.need_to_validate is set by the modules.
+ * @return on false a module init failed.
+ */
+int modstack_setup(struct module_stack* stack, const char* module_conf,
+       struct module_env* env);
+
+/**
+ * Desetup the modules, deinit, delete.
+ * @param stack: made empty.
+ * @param env: module env for module deinit() calls.
+ */
+void modstack_desetup(struct module_stack* stack, struct module_env* env);
+
+#endif /* SERVICES_MODSTACK_H */