diff -rNu ../../gateway/gw/bearerbox.c ./gw/bearerbox.c
--- ../../gateway/gw/bearerbox.c	Mon May 27 10:16:18 2002
+++ ./gw/bearerbox.c	Mon May 27 10:44:05 2002
@@ -22,6 +22,8 @@
 #include "shared.h"
 #include "dlr.h"
 
+#include "bearerbox_modules.h"
+
 /* global variables; included to other modules as needed */
 
 List *incoming_sms;
diff -rNu ../../gateway/gw/bearerbox_modules.h ./gw/bearerbox_modules.h
--- ../../gateway/gw/bearerbox_modules.h	Wed Dec 31 16:00:00 1969
+++ ./gw/bearerbox_modules.h	Mon May 27 10:44:05 2002
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002 Harrie Hazewinkel, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel."
+ *
+ * 4. The name of the Copyright holder must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel"
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESSED 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 APACHE GROUP OR
+ * ITS 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.
+ * ====================================================================
+ */
+#ifndef __BEARER_MODULES_H__
+#define __BEARER_MODULES_H__
+
+#include "gwlib/modules.h"
+
+kannel_module *module_array[] = {
+};
+
+int module_array_size = sizeof(module_array)/sizeof(kannel_module*);
+#endif /* __BEARER_MODULES_H__ */
diff -rNu ../../gateway/gw/mod_heartbeat.c ./gw/mod_heartbeat.c
--- ../../gateway/gw/mod_heartbeat.c	Wed Dec 31 16:00:00 1969
+++ ./gw/mod_heartbeat.c	Mon May 27 10:44:05 2002
@@ -0,0 +1,155 @@
+/*
+ * heartbeat.c - thread for sending heartbeat Msgs to bearerbox
+ */
+
+#include <signal.h>
+
+#include "gwlib/gwlib.h"
+#include "msg.h"
+#include "shared.h"
+#include "gwlib/modules.h"
+#include "mod_heartbeat.h"
+
+/*
+ * Each running heartbeat gets one of these.  They are collected in
+ * the heartbeats List.
+ */
+struct hb_info {
+    long thread;
+    double freq;
+    send_func_t *send_func;
+    load_func_t *load_func;
+    volatile sig_atomic_t running;
+};
+
+/* List of struct hb_info. */
+static List *heartbeats;
+/* The heartbeat frequentie. */
+static int heartbeat_freq = DEFAULT_HEARTBEAT;
+
+
+/*
+ * Look for a hb_info in a list, by thread number.
+ */
+static int find_hb(void *item, void *pattern)
+{
+    long *threadnrp;
+    struct hb_info *info;
+
+    info = item;
+    threadnrp = pattern;
+
+    return info->thread == *threadnrp;
+}
+
+static void heartbeat_thread(void *arg)
+{
+    struct hb_info *info;
+    time_t last_hb;
+
+    info = arg;
+    last_hb = 0;
+
+    while (info->running) {
+        Msg *msg;
+
+        gwthread_sleep(info->freq);
+
+        /*
+         * Because the sleep can be interrupted, we might end up sending
+         * heartbeats faster than the configured heartbeat frequency.
+         * This is not bad unless we send them way too fast.  Make sure
+         * our frequency is not more than twice the configured one.
+         */
+        if (difftime(last_hb, time(NULL)) < info->freq / 2)
+            continue;
+
+        msg = msg_create(heartbeat);
+        msg->heartbeat.load = info->load_func();
+        info->send_func(msg);
+        last_hb = time(NULL);
+    }
+}
+
+static long
+heartbeat_start(send_func_t *send_func,
+                     load_func_t *load_func)
+{
+    struct hb_info *info;
+
+    debug("mod_heartbeat", GW_DEBUG, "Start heartbeat");
+    info = gw_malloc(sizeof(*info));
+    info->send_func = send_func;
+    info->freq = heartbeat_freq;
+    info->load_func = load_func;
+    info->running = 1;
+    info->thread = gwthread_create(heartbeat_thread, info);
+    if (info->thread >= 0) {
+	if (heartbeats == NULL)
+	    heartbeats = list_create();
+	list_append(heartbeats, info);
+        return 0;
+    } else {
+        gw_free(info);
+        return -1;
+    }
+}
+
+static void
+heartbeat_stop(void)
+{
+    struct hb_info *info;
+
+    debug("mod_heartbeat", GW_DEBUG, "STOP heartbeat");
+
+    while (list_len(heartbeats)) {
+        debug("mod_heartbeat", GW_DEBUG, "yep");
+        info = list_extract_first(heartbeats);
+        if (info) {
+            info->running = 0;
+            gwthread_wakeup(info->thread);
+            gwthread_join(info->thread);
+        }
+         gw_free(info);
+    }
+    list_destroy(heartbeats, NULL);
+    heartbeats = NULL;
+}
+
+static int
+heartbeat_init(void)
+{
+    return 0;
+}
+
+static int
+heartbeat_log(void)
+{
+/* the hook in the core is not implemented yet */
+}
+
+static void
+heartbeat_exit(void)
+{
+
+}
+
+kannel_config config_parms[] = {
+    { "heartbeat", "smsbox", NULL },
+    NULL
+};
+
+kannel_module mod_heartbeat = {
+    1,                /* api version                                */
+    "heartbeat",      /* module identification                      */
+    config_parms,     /* module specific configuration parameters.  */
+                      /* For the moment not done, needs big rewrite */
+                      /* of existing configuration handling.        */
+    heartbeat_init,   /* module initialization                      */
+    heartbeat_start,  /* module start                               */
+    heartbeat_stop,   /* module start                               */
+    heartbeat_log,    /* module log           (not implemented yet) */
+    heartbeat_exit    /* module exit/cleanup  (not implemented yet) */
+    /* other */
+};
+
diff -rNu ../../gateway/gw/mod_heartbeat.h ./gw/mod_heartbeat.h
--- ../../gateway/gw/mod_heartbeat.h	Wed Dec 31 16:00:00 1969
+++ ./gw/mod_heartbeat.h	Mon May 27 10:44:05 2002
@@ -0,0 +1,15 @@
+/*
+ * heartbeat.h - thread for sending heartbeat Msgs to bearerbox
+ */
+
+#ifndef __MOD_HEARTBEAT_H__
+#define __MOD_HEARTBEAT_H__
+
+#include "gwlib/gwlib.h"
+#include "msg.h"
+
+#define DEFAULT_HEARTBEAT    30
+
+extern kannel_module mod_heartbeat;
+
+#endif /* __MOD_HEARTBEAT_H__ */
diff -rNu ../../gateway/gw/shared.h ./gw/shared.h
--- ../../gateway/gw/shared.h	Tue May 14 04:05:08 2002
+++ ./gw/shared.h	Mon May 27 10:44:05 2002
@@ -64,6 +64,10 @@
  * Send an Msg to the bearerbox, and destroy the Msg.
  */
 void write_to_bearerbox(Msg *msg);
+/*
+ * Associated typedef for send function.
+ */
+typedef void send_func_t(Msg *msg);
 
 /*
  * Validates an OSI date.
diff -rNu ../../gateway/gw/sms_modules.h ./gw/sms_modules.h
--- ../../gateway/gw/sms_modules.h	Wed Dec 31 16:00:00 1969
+++ ./gw/sms_modules.h	Mon May 27 10:44:05 2002
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002 Harrie Hazewinkel, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel."
+ *
+ * 4. The name of the Copyright holder must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel"
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESSED 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 APACHE GROUP OR
+ * ITS 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.
+ * ====================================================================
+ */
+#ifndef __SMS_MODULES_H__
+#define __SMS_MODULES_H__
+
+#include "gwlib/modules.h"
+#include "mod_heartbeat.h"
+
+extern kannel_module mod_heartbeat;
+
+kannel_module *module_array[] = {
+    &mod_heartbeat
+};
+
+int module_array_size = sizeof(module_array)/sizeof(kannel_module*);
+#endif /* __SMS_MODULES_H__ */
diff -rNu ../../gateway/gw/smsbox.c ./gw/smsbox.c
--- ../../gateway/gw/smsbox.c	Mon May 20 07:12:56 2002
+++ ./gw/smsbox.c	Mon May 27 10:44:05 2002
@@ -13,7 +13,6 @@
 #include "sms.h"
 #include "bb.h"
 #include "shared.h"
-#include "heartbeat.h"
 #include "html.h"
 #include "urltrans.h"
 #include "ota_prov_attr.h"
@@ -24,6 +23,7 @@
 #include <security/pam_appl.h>
 #endif
 
+#include "sms_modules.h"
 
 /*
  * Maximum number of octets in an SMS message. Note that this is 8 bit
@@ -46,7 +46,6 @@
 static Octstr *xmlrpc_url = NULL;
 static Octstr *bb_host;
 static char *pid_file;
-static int heartbeat_freq;
 static Octstr *accepted_chars = NULL;
 static int only_try_http = 0;
 static URLTranslationList *translations = NULL;
@@ -2692,7 +2691,6 @@
     bb_port = BB_DEFAULT_SMSBOX_PORT;
     bb_ssl = 0;
     bb_host = octstr_create(BB_DEFAULT_HOST);
-    heartbeat_freq = BB_DEFAULT_HEARTBEAT;
     logfile = NULL;
     lvl = 0;
 
@@ -2837,6 +2835,8 @@
     octstr_destroy(http_proxy_username);
     octstr_destroy(http_proxy_password);
     list_destroy(http_proxy_exceptions, octstr_destroy_item);
+
+    run_init();
 }
 
 
@@ -2853,7 +2853,6 @@
 int main(int argc, char **argv)
 {
     int cf_index;
-    long heartbeat_thread;
     Octstr *cfg_name;
 
     gwlib_init();
@@ -2897,14 +2896,15 @@
     connect_to_bearerbox(bb_host, bb_port, bb_ssl, NULL /* bb_our_host */);
 	/* XXX add our_host if required */
 
-    heartbeat_thread = heartbeat_start(write_to_bearerbox, heartbeat_freq,
-				       outstanding_requests);
+    run_start_thread(write_to_bearerbox,
+                                       outstanding_requests);
 
     read_messages_from_bearerbox();
 
     info(0, GW_NAME " smsbox terminating.");
 
-    heartbeat_stop(heartbeat_thread);
+    run_stop_thread();
+
     http_close_all_ports();
     gwthread_join_every(sendsms_thread);
     list_remove_producer(smsbox_requests);
diff -rNu ../../gateway/gw/smskannel.conf ./gw/smskannel.conf
--- ../../gateway/gw/smskannel.conf	Thu May  2 21:02:26 2002
+++ ./gw/smskannel.conf	Mon May 27 10:44:05 2002
@@ -53,7 +53,7 @@
 #log-file = "/tmp/smsbox.log"
 #log-level = 0
 #access-log = "access.log"
-
+heartbeat  = 50
 
 # SEND-SMS USERS
 
diff -rNu ../../gateway/gw/wap_modules.h ./gw/wap_modules.h
--- ../../gateway/gw/wap_modules.h	Wed Dec 31 16:00:00 1969
+++ ./gw/wap_modules.h	Mon May 27 10:44:05 2002
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002 Harrie Hazewinkel, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel."
+ *
+ * 4. The name of the Copyright holder must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel"
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESSED 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 APACHE GROUP OR
+ * ITS 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.
+ * ====================================================================
+ */
+#ifndef __WAP_MODULES_H__
+#define __WAP_MODULES_H__
+
+#include "gwlib/modules.h"
+#include "mod_heartbeat.h"
+
+extern kannel_module mod_heartbeat;
+
+kannel_module *module_array[] = {
+    &mod_heartbeat
+};
+
+int module_array_size = sizeof(module_array)/sizeof(kannel_module*);
+#endif /* __WAP_MODULES_H__ */
diff -rNu ../../gateway/gw/wapbox.c ./gw/wapbox.c
--- ../../gateway/gw/wapbox.c	Tue May 14 04:05:08 2002
+++ ./gw/wapbox.c	Mon May 27 10:44:05 2002
@@ -22,6 +22,8 @@
 #include "bb.h"
 #include "sms.h"
 
+#include "wap_modules.h"
+
 #ifdef HAVE_WTLS_OPENSSL
 #include <openssl/x509.h>
 #include "wap/wtls.h"
diff -rNu ../../gateway/gwlib/cfg.c ./gwlib/cfg.c
--- ../../gateway/gwlib/cfg.c	Mon Apr 29 18:11:34 2002
+++ ./gwlib/cfg.c	Mon May 27 10:44:05 2002
@@ -6,6 +6,8 @@
 
 
 #include "gwlib/gwlib.h"
+#include "gw/shared.h"
+#include "gwlib/modules.h"
 
 
 struct CfgGroup {
@@ -97,6 +99,10 @@
     
     groupstr = octstr_imm("group");
 
+    if (is_allowed_by_module(group, variable)) {
+        return 1;
+    }
+
     #define OCTSTR(name) \
     	if (octstr_compare(octstr_imm(#name), variable) == 0) \
 	    return 1;
@@ -122,6 +128,9 @@
 
 static int is_single_group(Octstr *query)
 {
+    if (is_single_group_by_module(query))
+        return 1;
+
     #define OCTSTR(name)
     #define SINGLE_GROUP(name, fields) \
     	if (octstr_compare(octstr_imm(#name), query) == 0) \
diff -rNu ../../gateway/gwlib/modules.c ./gwlib/modules.c
--- ../../gateway/gwlib/modules.c	Wed Dec 31 16:00:00 1969
+++ ./gwlib/modules.c	Mon May 27 10:44:05 2002
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2002 Harrie Hazewinkel, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel."
+ *
+ * 4. The name of the Copyright holder must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel"
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESSED 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 APACHE GROUP OR
+ * ITS 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.
+ * ====================================================================
+ */
+
+#include <stdio.h>
+
+#include "gw/shared.h"
+
+/* Includes all modules. */
+#include "modules.h"
+
+int
+is_allowed_by_module(Octstr *group, Octstr *variable) {
+
+    if (module_array != NULL) {
+        int i = 0;
+        while (i < module_array_size) {
+            kannel_config *config = (*module_array[i]).config;
+            if (config) {
+                while (config->item) {
+                    if (octstr_str_compare(group, config->ofgroup) == 0) {
+                        if (octstr_str_compare(variable, config->item) == 0) {
+                            return 1;
+                        }
+                    }
+                    ++config;
+                }
+            }
+            i++;
+        }
+        return 0;
+    }
+}
+
+int
+is_single_group_by_module(Octstr *query) {
+
+    debug("core.modules", GW_DEBUG, "group testing '%s'", octstr_get_cstr(query));
+    return 0;
+}
+
+
+int
+run_init(void) {
+    if (module_array != NULL) {
+        int i = 0;
+        while (i < module_array_size) {
+            init_function function = (*module_array[i]).func_init;
+            if (function) {
+                if ((*function)()) {
+                    error(GW_ERROR, "Oh oh, I am in trouble");
+                    exit(0);
+                }
+            }
+            i++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
+int
+run_start_thread(send_func_t *send_func,
+                                     load_func_t *load_func) {
+    if (module_array != NULL) {
+        int i = 0;
+
+        debug("core.modules", GW_DEBUG, "we have %d modules", module_array_size);
+
+        while (i < module_array_size) {
+            start_thread_function function = (*module_array[i]).func_start_thread;
+            if (function) {
+                if ((*function)(send_func, load_func)) {
+                    error(GW_ERROR, "Oh oh, I am in trouble");
+                    exit(0);
+                }
+            }
+            i++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
+int
+run_stop_thread(void) {
+    if (module_array != NULL) {
+        int i = 0;
+
+        debug("core.modules", GW_DEBUG, "we have %d modules", module_array_size);
+
+        while (i < module_array_size) {
+            stop_thread_function function = (*module_array[i]).func_stop_thread;
+            if (function) {
+                (*function)();
+            }
+            i++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
+int
+run_log(void) {
+    if (module_array != NULL) {
+        int i = 0;
+        while (i < module_array_size) {
+            log_function function = (*module_array[i]).func_log;
+            if (function) {
+                if ((*function)()) {
+                    error(GW_ERROR, "Oh oh, I am in trouble");
+                    exit(0);
+                }
+            }
+            i++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
+int
+run_exit(void) {
+    if (module_array != NULL) {
+        int i = 0;
+        while (i < module_array_size) {
+            exit_function function = (*module_array[i]).func_exit;
+            if (function) {
+                (*function)();
+            }
+            i++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
diff -rNu ../../gateway/gwlib/modules.h ./gwlib/modules.h
--- ../../gateway/gwlib/modules.h	Wed Dec 31 16:00:00 1969
+++ ./gwlib/modules.h	Mon May 27 10:44:05 2002
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002 Harrie Hazewinkel, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel."
+ *
+ * 4. The name of the Copyright holder must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Harrie Hazewinkel"
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
+ * EXPRESSED 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 APACHE GROUP OR
+ * ITS 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.
+ * ====================================================================
+ */
+#ifndef __MODULES_H__
+#define __MODULES_H__
+
+/* This is here defined, but should be in some other place; TBD */
+typedef long load_func_t(void);
+
+typedef int (*config_function) (void);
+
+/* A structure to maintian configuration specific items */
+typedef struct kannel_config_s {
+  char *item;
+  char *ofgroup;
+  config_function handler;
+} kannel_config;
+
+/* Tyepdef for the hook functions. */
+typedef int  (*init_function)         (void /* parameters */);
+typedef long (*start_thread_function) (send_func_t *send_func,
+                                       load_func_t *load_func);
+typedef void (*stop_thread_function)  (void);
+typedef int  (*log_function)          (void /* parameters */);
+typedef void (*exit_function)         (void /* parameters */);
+
+/* The module structure definition. */
+typedef struct kannel_module_s {
+    int api_version;               /* API version for compatibility check. */
+    char *module_name;             /* module identification. */
+    kannel_config *config;         /* module specific configuration parameters. */
+    init_function func_init;
+    start_thread_function func_start_thread;
+    stop_thread_function func_stop_thread;
+    log_function func_log;
+    exit_function func_exit;
+    /* other */
+} kannel_module;
+
+/* The external modules array;
+ * needs to be defined in a process specific file.
+ */
+extern kannel_module *module_array[];
+extern int module_array_size;
+
+/* The run hooks function definitions. */
+int is_allowed_by_module(Octstr *group, Octstr *variable);
+int is_single_group_by_module(Octstr *query);
+int run_init(void);
+int run_start_thread(send_func_t *send_func,
+                                     load_func_t *load_func);
+int run_stop_thread(void);
+int run_log(void);
+int run_exit(void);
+
+#endif /* __MODULES_H__ */
