diff -ru -I Id: -x CVS -N dbmail/bounce.c dbmail.working/bounce.c
--- dbmail/bounce.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/bounce.c	2002-11-07 09:18:23.000000000 +1300
@@ -10,6 +10,7 @@
 #include "mime.h"
 #include "db.h"
 #include "debug.h"
+#include "config.h"
 
 extern struct list mimelist;  
 extern struct list users;  
@@ -24,10 +25,9 @@
   char *postmaster;
 
   /* reading configuration from db */
-  dbmail_from_address = db_get_config_item ("DBMAIL_FROM_ADDRESS",CONFIG_MANDATORY);
-  sendmail = db_get_config_item ("SENDMAIL", CONFIG_MANDATORY);
-	
-  postmaster = db_get_config_item ("POSTMASTER",CONFIG_MANDATORY);
+  dbmail_from_address = get_config_item (DBMAIL_FROM_ADDRESS, "DBMAIL_FROM_ADDRESS");
+  sendmail = get_config_item (SENDMAIL, "SENDMAIL");
+  postmaster = get_config_item (POSTMASTER, "POSTMASTER");
   
   trace (TRACE_DEBUG,"bounce(): creating bounce message for bounce type [%d]",type);
 		
@@ -171,10 +171,6 @@
 	break;
       }
     }
-
-  my_free (dbmail_from_address);
-  my_free (postmaster);
-  my_free (sendmail);
   return 0;
 }
 
diff -ru -I Id: -x CVS -N dbmail/config.c dbmail.working/config.c
--- dbmail/config.c	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/config.c	2002-11-08 13:26:44.000000000 +1300
@@ -0,0 +1,531 @@
+/*
+** config.c
+** Functions for reading configurations (file and command line)
+*/
+
+#include "list.h"
+#include "config.h"
+#include "debug.h"
+#include "db.h"
+#include "hash.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <getopt.h>
+
+#define LINE_BUFFER_SIZE 516
+#define HASH_TABLE_INIT_SIZE 60
+#define YES 1
+#define NO 0
+
+static struct hash_table table, *config_items;
+void read_config_file(char *file_name, int override);
+
+static const struct option long_options[] =
+{
+  {"help",                     no_argument, 0, 1},
+  {"HELP",                     no_argument, 0, 1},
+  {"CONFIG_FILE",              required_argument, 0, 2},
+  {"MAIL_HOST",                required_argument, 0, 0},
+  {"MAIL_USER",                required_argument, 0, 0},
+  {"MAIL_PASS",                required_argument, 0, 0},
+  {"MAIL_PORT",                required_argument, 0, 0},
+  {"MAILDATABASE",             required_argument, 0, 0},
+  {"MAIL_HOST_READ",           required_argument, 0, 0},
+  {"MAIL_USER_READ",           required_argument, 0, 0},
+  {"MAIL_PASS_READ",           required_argument, 0, 0},
+  {"MAIL_PORT_READ",           required_argument, 0, 0},
+  {"MAILDATABASE_READ",        required_argument, 0, 0},
+  {"AUTH_HOST",                required_argument, 0, 0},
+  {"AUTH_USER",                required_argument, 0, 0},
+  {"AUTH_PASS",                required_argument, 0, 0},
+  {"AUTH_PORT",                required_argument, 0, 0},
+  {"USERDATABASE",             required_argument, 0, 0},
+  {"AUTH_HOST_READ",           required_argument, 0, 0},
+  {"AUTH_USER_READ",           required_argument, 0, 0},
+  {"AUTH_PASS_READ",           required_argument, 0, 0},
+  {"AUTH_PORT_READ",           required_argument, 0, 0},
+  {"USERDATABASE_READ",        required_argument, 0, 0},
+  {"TRACE_LEVEL",              required_argument, 0, 0}, 
+  {"TRACE_TO_SYSLOG",          required_argument, 0, 0},
+  {"TRACE_VERBOSE",            required_argument, 0, 0},
+  {"SENDMAIL",                 required_argument, 0, 0},
+  {"DBMAIL_FROM_ADDRESS",      required_argument, 0, 0},
+  {"POSTMASTER",               required_argument, 0, 0},
+  {"POP3D_EFFECTIVE_USER",     required_argument, 0, 0},
+  {"POP3D_EFFECTIVE_GROUP",    required_argument, 0, 0},
+  {"POP3D_BIND_IP",            required_argument, 0, 0},
+  {"POP3D_BIND_PORT",          required_argument, 0, 0},
+  {"POP3D_DEFAULT_CHILD",      required_argument, 0, 0},
+  {"POP3D_MAX_CHILD",          required_argument, 0, 0},
+  {"POP3D_CHILD_MAX_CONNECTS", required_argument, 0, 0},
+  {"POP3D_CHILD_TIMEOUT",      required_argument, 0, 0},
+  {"POP3D_IP_RESOLVE",         required_argument, 0, 3},
+  {"IMAPD_EFFECTIVE_USER",     required_argument, 0, 0},
+  {"IMAPD_EFFECTIVE_GROUP",    required_argument, 0, 0},
+  {"IMAPD_BIND_IP",            required_argument, 0, 0},
+  {"IMAPD_BIND_PORT",          required_argument, 0, 0},
+  {"IMAPD_DEFAULT_CHILD",      required_argument, 0, 0},
+  {"IMAPD_MAX_CHILD",          required_argument, 0, 0},
+  {"IMAPD_CHILD_MAX_CONNECTS", required_argument, 0, 0},
+  {"IMAPD_DAEMONIZES",         required_argument, 0, 3},
+  {"IMAPD_CHILD_TIMEOUT",      required_argument, 0, 0},
+  {"SMTPD_EFFECTIVE_USER",     required_argument, 0, 0},
+  {"SMTPD_EFFECTIVE_GROUP",    required_argument, 0, 0},
+  {"SMTPD_BIND_IP",            required_argument, 0, 0},
+  {"SMTPD_BIND_PORT",          required_argument, 0, 0},
+  {"SMTPD_DEFAULT_CHILD",      required_argument, 0, 0},
+  {"SMTPD_MAX_CHILD",          required_argument, 0, 0},
+  {"SMTPD_CHILD_MAX_CONNECTS", required_argument, 0, 0},
+  {"SMTPD_DAEMONIZES",         required_argument, 0, 3},
+  {"SMTPD_CHILD_TIMEOUT",      required_argument, 0, 0},
+  {"DBMAIL_POP_BEFORE_SMTP",   required_argument, 0, 3},
+  {"DBMAIL_IMAP_BEFORE_SMTP",  required_argument, 0, 3},
+  {"AUTO_CREATE_MAILBOX",      required_argument, 0, 3},
+  {0, 0, 0, 0}
+};
+
+
+/* prints the configuration usage options
+*/
+void config_usage (void)
+{
+  puts ("\nConfig usage: Reads configurable parameters from the\n\
+              command line or from a configuration file (default\n\
+              file specified in config.h CONFIG_FILE, usually\n\
+              'dbmail.config').\n\
+\n\
+   --help\n\
+         prints this usage message\n\
+   --CONFIG_FILE <file_name>\n\
+         configuration file (default, see above)\n\
+\n\
+ Database settings\n\
+   --MAIL_HOST <host>\n\
+         mail database host\n\
+   --MAIL_USER <user>\n\
+         mail database user\n\
+   --MAIL_PASS <password>\n\
+         mail database users password\n\
+   --MAIL_PORT <port>\n\
+         mail database listening port\n\
+   --MAILDATABASE <db name>\n\
+         mail database\n\
+   --MAIL_HOST_READ <host>\n\
+         mail read database host\n\
+   --MAIL_USER_READ <user>\n\
+         mail read database user\n\
+   --MAIL_PASS_READ <password>\n\
+         mail read database users password\n\
+   --MAIL_PORT_READ <port>\n\
+         mail read database listening port\n\
+   --MAILDATABASE_READ <db name>\n\
+         mail read database\n\
+   --AUTH_HOST <host>\n\
+         auth database host\n\
+   --AUTH_USER <user>\n\
+         auth database user\n\
+   --AUTH_PASS <password>\n\
+         auth database users password\n\
+   --AUTH_PORT <port>\n\
+         auth database listening port\n\
+   --USERDATABASE <db name>\n\
+         auth read database\n\
+   --AUTH_HOST_READ <host>\n\
+         auth read database host\n\
+   --AUTH_USER_READ <user>\n\
+         auth read database user\n\
+   --AUTH_PASS_READ <password>\n\
+         auth read database users password\n\
+   --AUTH_PORT_READ <port>\n\
+         auth read database listening port\n\
+   --USERDATABASE_READ <db name>\n\
+         auth read database\n\
+\n\
+ System wide settings\n\
+   --TRACE_LEVEL <0..5>\n\
+         for debugging purposes level 5\n\
+         is maximum debugging, level 2\n\
+         logs normal operations\n\
+   --TRACE_TO_SYSLOG <1|0>\n\
+         enables tracing messages to SYSLOG\n\
+         1 traces to syslog, 0 doesn't\n\
+   --TRACE_VERBOSE <1|0>\n\
+         enables tracing messages to STDOUT\n\
+         1 traces verbose, 0 doesn't\n\
+\n\
+ dbmail-smtp settings\n\
+   --SENDMAIL <location>\n\
+         location of sendmail executable\n\
+         needed for bouncing mail\n\
+   --DBMAIL_FROM_ADDRESS <email>\n\
+         email address where bounces come from\n\
+   --POSTMASTER <email>\n\
+         postmaster email address\n\
+\n\
+ dbmail-pop3d settings\n\
+   --POP3D_EFFECTIVE_USER <user>\n\
+         user that dbmail-pop3d will run as (if\n\
+         dbmail-pop3d is run on a port < 1024 dbmail-pop3d\n\
+         will have to be started by root)\n\
+   --POP3D_EFFECTIVE_GROUP <group>\n\
+         group that dbmail-pop3d will run as\n\
+   --POP3D_BIND_IP <ip address>\n\
+         ipaddress the dbmail-pop3d server has to\n\
+         bind to, * for all addresses\n\
+   --POP3D_BIND_PORT <port>\n\
+         port number the dbmail-pop3d server has to\n\
+         bind to\n\
+   --POP3D_DEFAULT_CHILD <min children>\n\
+         number of children dbmail-pop3d defaultly forks\n\
+         to for busy sites this should be set quite high for\n\
+         best performance. the pop server will always keep\n\
+         this number of children alive\n\
+   --POP3D_MAX_CHILD <max children>\n\
+         maximum of children the dbmail-pop3d is allowed\n\
+         to fork to this is also the maximum concurrent\n\
+         connections\n\
+   --POP3D_CHILD_MAX_CONNECTS <number>\n\
+         maximum number of connections a default childs\n\
+         makes. after this it will commit suicide\n\
+   --POP3D_CHILD_TIMEOUT <seconds>\n\
+         number of seconds before the dbmail-pop3d should\n\
+         shutdown a connection which is being idle\n\
+   --POP3D_IP_RESOLVE <1|0>\n\
+         whether the dbmail-pop3d should resolve IP numbers\n\
+         to DNS names in the log this could make a connection\n\
+         slower since dbmail-pop3d has to wait for a resolve\n\
+         before it's able to continue\n\
+\n\
+ dbmail-imapd settings\n\
+   --IMAPD_EFFECTIVE_USER <user>\n\
+         user that dbmail-imapd will run as  (if dbmail-imapd\n\
+         is run on a port < 1024 dbmail-imapd will have to be\n\
+         started by root)\n\
+   --IMAPD_EFFECTIVE_GROUP <group>\n\
+         group that dbmail-imapd will run as\n\
+   --IMAPD_BIND_IP <ip address>\n\
+         ipaddress that the dbmail-imapd has to bind to, * from\n\
+         all addresses.\n\
+   --IMAPD_BIND_PORT <port>\n\
+         port that the dbmail-imapd has to bind to\n\
+   --IMAPD_DEFAULT_CHILD <min children>\n\
+         number of children dbmail-imapd defaultly forks to\n\
+   --IMAPD_MAX_CHILD <max children>\n\
+         maximum of children the dbmail-imapd is allowed to\n\
+         fork to\n\
+   --IMAPD_CHILD_MAX_CONNECTS <number>\n\
+         maximum number of connections a default childs makes. after\n\
+         this it will commit suicide\n\
+   --IMAPD_DAEMONIZES <1|0>\n\
+         denotes wheter the IMAP server should daemonize. This\n\
+         should be set to yes in a production environment\n\
+   --IMAPD_CHILD_TIMEOUT <seconds>\n\
+         number of seconds before the dbmail-imapd should shutdown\n\
+         a connection which is being idle. for a IMAP4r1 compliant\n\
+         server the minimum of this value is 1800 (30 minutes)\n\
+\n\
+ Full MTA dbmail-smtpd settings\n\
+   --SMTPD_EFFECTIVE_USER <user>\n\
+         user that dbmail-smtpd will run as (if dbmail-smtpd\n\
+         is run on a port < 1024 dbmail-smtpd will have to be started\n\
+         by root)\n\
+   --SMTPD_EFFECTIVE_GROUP <group>\n\
+         group that dbmail-smtpd will run as\n\
+   --SMTPD_BIND_IP <ip address>\n\
+         ipaddress that the dbmail-smtpd has to bind to, * from\n\
+         all addresses\n\
+   --SMTPD_BIND_PORT <port>\n\
+         port that the dbmail-smtpd has to bind to\n\
+   --SMTPD_DEFAULT_CHILD <min children>\n\
+         number of children dbmail-smtpd defaultly forks to\n\
+   --SMTPD_MAX_CHILD <max children>\n\
+         maximum of children the dbmail-smtpd is allowed to fork to\n\
+   --SMTPD_CHILD_MAX_CONNECTS <number>\n\
+         maximum number of connections a default childs makes. after\n\
+         this it will commit suicide\n\
+   --SMTPD_DAEMONIZES <1|0>\n\
+         enotes wheter the SMTP server should daemonize. This\n\
+         should be set to yes in a production environment\n\
+   --SMTPD_CHILD_TIMEOUT <seconds>\n\
+         number of seconds before the dbmail-smtpd should\n\
+         shutdown a connection which is being idle\n\
+\n\
+ Other settings\n\
+   --DBMAIL_POP_BEFORE_SMTP <1|0>\n\
+   --DBMAIL_IMAP_BEFORE_SMTP <1|0>\n\
+         enables the POP_BEFORE_SMTP feature. Before you can use\n\
+         this feature you'll need to run sql/pop_before_smtp.sql to\n\
+         create the right tables\n\
+   --AUTO_CREATE_MAILBOX <1|0>\n\
+         if set, mailboxes are automatically created when not exist\n\
+\n");
+}
+
+
+/*
+ * Init configuration parameters.
+ * Accepts: argc     number of command line args
+ *          argv     the args
+ *          usage    pointer to a usage function 
+ *
+ * 1 First parse command line parameters from argv.
+ * 2 Read the configuration file 'CONFIG_FILE'
+ *
+ * Note: Only parameters starting with '--' are parsed. The '-' parameters
+ *       are handled elsewhere (i.e. in the different main functions).
+ * Note2:The argc and argv is modified to not include any '--' parameters.
+ *       This is because 'init_config' doesn't want to mess up for the original
+ *       code which depends on the position of some parameters (e.g. main.c)
+ *
+ */
+void init_config(int *argc, char *argv[], void (*usage) ())
+{
+   int c, option_index=0, i, cp_argc=*argc;
+   char *cp_argv[cp_argc];
+   char *file_name=NULL;
+
+	// Construct the hash table
+	config_items=&table;
+   construct_table(config_items, HASH_TABLE_INIT_SIZE);
+
+   // Make a copy of argv. (getopt messes up the order
+   // of the arguments..?)
+   for(i=0; i<cp_argc; i++)
+   {
+      cp_argv[i] = (char *) strdup(argv[i]);
+   }
+   opterr=0;   // Turn off the error message `getopt' prints for unrecognized options.
+   while ((c=getopt_long_only(cp_argc, cp_argv, "", long_options,
+			  &option_index)) != EOF)
+   {
+      switch(c) {
+         case 0: // Normal parameters
+             insert((char*)long_options[option_index].name,
+                    optarg, config_items);
+             trace (TRACE_DEBUG, "init_config(): key [%s] value [%s]",
+                    (char*)long_options[option_index].name, optarg);
+             break;
+         case 1: // HELP, help
+             config_usage();
+             if(*usage)
+               (*usage)();
+             exit(0);
+             break;
+         case 2: // CONFIG-FILE
+             file_name = (char*)malloc(strlen(optarg)+1);
+             sprintf(file_name, "%s", optarg);
+             trace (TRACE_DEBUG, "init_config(): config_file [%s]", optarg);
+             break;
+         case 3: // 1|0 type parameters
+             // Only allow '1' or '0'
+             if(strlen(optarg)>1 || !isdigit(*optarg) || 
+                atoi(optarg)>1 || atoi(optarg)<0 )
+             {
+               config_usage();
+               if(*usage)
+                 (*usage)();
+               fprintf(stderr, "Illegal value for parameter --%s=%s\n", 
+                       (char*)long_options[option_index].name, optarg);
+               fprintf(stderr, "Only 1 or 0 allowed (yes or no)\n\n");
+               exit(2);
+             }
+             insert((char*)long_options[option_index].name,
+                    optarg, config_items);
+             trace (TRACE_DEBUG, "init_config(): key [%s] value [%s]",
+                    (char*)long_options[option_index].name, optarg);
+             break;
+         case 4: // Parameters without arguments
+             insert((char*)long_options[option_index].name,
+                    "1", config_items);
+             trace (TRACE_DEBUG, "init_config(): key [%s] value set",
+                    (char*)long_options[option_index].name);
+             break;
+         default:
+            // Only bother with parameters starting with '--'
+            if (strncmp("--", cp_argv[optind-1], 2)==0)
+            {
+               config_usage();
+               if(*usage)
+                 (*usage)();
+               fprintf(stderr, "Illegal parameter '%s' (or missing argument)\n\n", cp_argv[optind-1]);
+               exit(1);
+            }
+         break;
+      }
+   }
+
+   // Read the config file, but don't update fields that have been set by
+   // command line argmunents
+   read_config_file(file_name, NO);
+
+
+   // Update argc and argv to not contain any '--' parameters
+   for(i=cp_argc-1; i>0; i--)
+   {
+      if (strncmp("--", argv[i], 2)==0)
+      {
+         *argc=i;
+      }
+   }
+   for(i=cp_argc-1; i>*argc; i--)
+   {
+      argv[i]=NULL;
+   }
+   
+   // Reset the 'getopt' external variables. If getopt
+   // wants to be used again (e.g. maintenance.c)
+   optind = 1; optopt = 63; opterr = 1; optarg = NULL;
+}
+
+
+/*
+ * Read the configuration file and insert the found values in the
+ * 'config_items' hash table.
+ * Accepts: file_name: name of file to read (default CONFIG_FILE)
+ *	         override: if no (0) do not change a value already in the hash table
+*/
+void read_config_file (char *file_name, int override)
+{
+   FILE *configfile;
+   char *readbuf, *field, *val, *fname, *workptr;
+   int i=0;
+
+   readbuf = (char *)malloc(LINE_BUFFER_SIZE);
+
+   fname = CONFIG_FILE;
+   if (file_name != NULL)
+      fname = file_name;
+
+   trace (TRACE_DEBUG, "read_config_file(): reading configuration for %s...", fname);
+   configfile = fopen(fname, "r");     // open the configuration file
+   if (configfile == NULL)             // error test
+   {
+      trace (TRACE_ERROR, "read_config_file: Can not open input file [%s]", fname);
+      return;
+   }
+
+   while ( NULL != fgets (readbuf, LINE_BUFFER_SIZE, configfile))
+   {
+      i++;
+
+      // clip off optional comment tail indicated by a '#'
+      if( NULL != (workptr = strchr( readbuf, '#' )))
+         *workptr = '\0';
+      else
+         workptr = readbuf + strlen( readbuf );
+
+      // clip off trailing and leading white space
+      workptr--;
+      while( isspace( *workptr ) && workptr >= readbuf )
+         *workptr-- = '\0';
+      workptr = readbuf;
+      while( isspace( *workptr ))
+         workptr++;
+      if( 0 == strlen( workptr ))
+         continue;
+
+      field = strtok(workptr, " =");
+      if( field != NULL )
+      {
+         // strip leading white and a 'late' = from value part.
+         val = strtok( NULL, "" );
+         while( isspace( *val ))
+             val++;
+         if( '=' == *val )
+             val++;
+         while( isspace( *val ))
+             val++;
+
+         if (!val)
+         {
+            trace (TRACE_ERROR, "read_config_file: Config read error on line: %d", i);
+            trace (TRACE_ERROR, "read_config_file: readbuf: %s val: %s field: %s", readbuf, val, field);
+         }
+         else
+         {
+            if(override || lookup(field, config_items)==NULL)
+            {
+               insert(field, val, config_items);
+               trace (TRACE_DEBUG, "read_config_file(): key [%s] value [%s]", field, val);
+            }
+         }
+   	}
+	}
+	fclose(configfile);
+}
+
+/*
+** Search and return the config item specified by 'item'. If 'item'
+** isn't found return the 'def' value instead.
+*/
+char *get_config_item (char *def, char *item)
+{
+   char *result = NULL;
+   void *value;
+
+   // Check if the item table has been initialized.
+   if( config_items == NULL )
+   {
+      read_config_file(NULL, NO);
+   }
+
+   // Search the config_items hash table for the value specified by 'item'
+   value = lookup(item, config_items);
+   if (value!=NULL)
+   {
+      result=value;
+      trace (TRACE_DEBUG, "get_config_item(): '%s' value [%s]", item, result);
+   }
+   else
+   {
+      result=def;
+      trace (TRACE_DEBUG, "get_config_item(): '%s' def [%s]", item, result);
+   }
+
+   // returns null if *def=NULL and not in configuration file
+
+   return result;
+}
+
+
+/*
+** Search and return the config item specified by 'item'. If 'item'
+** isn't found return the 'def' value instead.
+*/
+int get_config_item_int (int def, char *item)
+{
+   int result;
+   char *value, *ptr;
+
+   // Check if the item table has been initialized.
+   if( config_items == NULL )
+   {
+      read_config_file(NULL, NO);
+   }
+
+   // Search the config_items hash table for the value specified by 'item'
+   value = lookup(item, config_items);
+   if (value!=NULL)
+   {
+      for(ptr=value; *ptr; ptr++)
+      {
+         if(!isdigit(*ptr))
+         {
+            trace (TRACE_FATAL, "get_config_item_int(): [%s] no number", value);
+         }
+      }
+      result=atoi(value);
+      trace (TRACE_DEBUG, "get_config_item(): '%s' value [%i]", item, result);
+   }
+   else
+   {
+      result=def;
+      trace (TRACE_DEBUG, "get_config_item(): '%s' def [%i]", item, result);
+   }
+
+   return result;
+}
diff -ru -I Id: -x CVS -N dbmail/db.h dbmail.working/db.h
--- dbmail/db.h	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/db.h	2002-11-07 15:21:10.000000000 +1300
@@ -101,6 +101,7 @@
 int db_connect();
 int db_disconnect();
 int db_query (const char *thequery);
+int db_query_read (const char *thequery);
 
 char *db_get_config_item (char *item, int type);
 int db_clear_config();
diff -ru -I Id: -x CVS -N dbmail/config.h dbmail.working/config.h
--- dbmail/config.h	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/config.h	2002-11-13 09:31:36.000000000 +1300
@@ -1,7 +1,6 @@
-/* $Id: config.h,v 1.24 2002/06/19 14:45:12 roel Exp $ 
+/* $Id: config.h,v 1.4 2002/11/12 20:31:36 root Exp $ 
  * (c) 2000-2001 IC&S, The Netherlands */
 
-
 #ifndef  _CONFIG_H
 #define  _CONFIG_H
 
@@ -12,18 +11,88 @@
 #include <unistd.h>
 #include <syslog.h>
 
+#define yes 1
+#define no  0
+#define UID_SIZE 70
+
 /* DATABASE SPECIFIC */
+#define CONFIG_FILE "/etc/dbmail/dbmail.config"
+
 #define MAIL_HOST "/tmp"
 #define MAIL_USER "dbmail"
-#define MAIL_PASS "dbma1l"
-#define MAILDATABASE "dbmail"
+#define MAIL_PASS ""
+#define MAIL_PORT 3306
+#define MAILDATABASE "dbmail_store"
 
 #define AUTH_HOST "/tmp"
 #define AUTH_USER "dbmail"
-#define AUTH_PASS "dbma1l"
-#define USERDATABASE "dbmail"
-
-#define UID_SIZE 70
-
+#define AUTH_PASS ""
+#define AUTH_PORT 3306
+#define USERDATABASE "dbmail_auth"
+
+#define MAIL_HOST_READ "/tmp"
+#define MAIL_USER_READ "dbmail"
+#define MAIL_PASS_READ ""
+#define MAIL_PORT_READ 3306
+#define MAILDATABASE_READ "dbmail_store"
+
+#define AUTH_HOST_READ "/tmp"
+#define AUTH_USER_READ "dbmail"
+#define AUTH_PASS_READ ""
+#define AUTH_PORT_READ 3306
+#define USERDATABASE_READ "dbmail_auth"
+
+/* SYSTEM WIDE SETTINGS */
+#define TRACE_LEVEL 2      // 0-5
+#define TRACE_TO_SYSLOG 1  // 1 or 0 
+#define TRACE_VERBOSE 0    // 1 or 0
+
+/* DBMAIL-SMTP SETTINGS */
+#define SENDMAIL "/usr/sbin/sendmail"
+#define DBMAIL_FROM_ADDRESS "dbmail-bounce@dbmail.org"
+#define POSTMASTER "dbmail@dbmail.org"
+
+/* DBMAIL-POP3D SETTINGS */
+#define POP3D_EFFECTIVE_USER "nobody"
+#define POP3D_EFFECTIVE_GROUP "nogroup"
+#define POP3D_BIND_IP "*"
+#define POP3D_BIND_PORT "110"
+#define POP3D_DEFAULT_CHILD 30
+#define POP3D_MAX_CHILD 50
+#define POP3D_CHILD_MAX_CONNECTS 10000
+#define POP3D_CHILD_TIMEOUT 300
+#define POP3D_IP_RESOLVE yes
+
+/* DBMAIL-IMAPD SETTINGS */
+#define IMAPD_EFFECTIVE_USER "nobody"
+#define IMAPD_EFFECTIVE_GROUP "nogroup"
+#define IMAPD_BIND_IP "*"
+#define IMAPD_BIND_PORT "143"
+#define IMAPD_DEFAULT_CHILD 5
+#define IMAPD_MAX_CHILD 15
+#define IMAPD_CHILD_MAX_CONNECTS 1000
+#define IMAPD_DAEMONIZES yes
+#define IMAPD_CHILD_TIMEOUT 3000
+
+/* FULL MTA DBMAIL-SMTPD SETTINGS */
+#define SMTPD_EFFECTIVE_USER "nobody"
+#define SMTPD_EFFECTIVE_GROUP "nogroup"
+#define SMTPD_BIND_IP "*"
+#define SMTPD_BIND_PORT "25"
+#define SMTPD_DEFAULT_CHILD 20
+#define SMTPD_MAX_CHILD 30
+#define SMTPD_CHILD_MAX_CONNECTS 1000
+#define SMTPD_DAEMONIZES yes
+#define SMTPD_CHILD_TIMEOUT 3000
+
+/* OTHER SETTINGS */
+#define DBMAIL_POP_BEFORE_SMTP  no
+#define DBMAIL_IMAP_BEFORE_SMTP no
+
+/* PROTOTYPES */
+void init_config(int *argc, char *argv[], void (*usage) ());
+char *get_config_item (char *def, char *item);
+int get_config_item_int (int def, char *item);
+void config_usage (void);
 
 #endif
diff -ru -I Id: -x CVS -N dbmail/dbmail.conf dbmail.working/dbmail.conf
--- dbmail/dbmail.conf	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/dbmail.conf	1970-01-01 12:00:00.000000000 +1200
@@ -1,157 +0,0 @@
-# $Id: dbmail.conf,v 1.86 2002/06/27 10:27:11 roel Exp $
-# (c) 2000-2001 IC&S, The Netherlands 
-#
-# Configuration file for DBMAIL 
-# This configuration file needs to be run through dbmail-config to be effective
-# after that, changes are effective inmediatly 
-
-
-################### SYSTEM WIDE SETTINGS #####################
-
-
-# TRACE_LEVEL is for debugging purposes
-# level 5 is maximum debugging, level 2 logs normal operations
-TRACE_LEVEL=2
-
-# TRACE_TO_SYSLOG enables tracing messages to SYSLOG 
-# 1 traces to syslog, 0 doesn't
-TRACE_TO_SYSLOG=1
-
-# TRACE_VERBOSE enables tracing messages to STDOUT
-# 1 traces verbose, 0 doesn't
-# You should not use verbose tracing in a production environment
-TRACE_VERBOSE=0
-
-
-
-################### DBMAIL-SMTP SETTINGS #####################
-
-# SENDMAIL is the location of your sendmail executable
-# this is needed for boucing mail
-SENDMAIL=/usr/sbin/sendmail
-
-# DBMAIL_FROM_ADDRESS is the email address where bounces come from 
-# this can ofcourse be a DBMAIL account
-DBMAIL_FROM_ADDRESS=dbmail-bounce@dbmail.org
-
-# POSTMASTER is the postmaster's email address (which is used in the bounce messages)
-POSTMASTER=dbmail@dbmail.org
-
-
-################### DBMAIL-POP3D SETTINGS #####################
-
-# POP3D_EFFECTIVE_USER is the user that dbmail-pop3d will run as
-# (if dbmail-pop3d is run on a port < 1024 dbmail-pop3d will have to be started by root)
-POP3D_EFFECTIVE_USER=nobody
-
-# POP3D_EFFECTIVE_GROUP is the group that dbmail-pop3d will run as 
-POP3D_EFFECTIVE_GROUP=nogroup
-
-# POP3D_BIND_IP is the ipaddress the dbmail-pop3d server has to bind to, * for all addresses
-POP3D_BIND_IP=*
-
-# POP3D_BIND_PORT is the port number the dbmail-pop3d server has to bind to. 
-POP3D_BIND_PORT=110
-
-# POP3D_DEFAULT_CHILD is the number of children dbmail-pop3d defaultly forks to
-# for busy sites this should be set quite high for best performance.
-# the pop server will always keep this number of childs alive 
-POP3D_DEFAULT_CHILD=30
-
-# POP3D_MAX_CHILD is the maximum of children the dbmail-pop3d is allowed to fork to
-# this is also the maximum concurrent connections
-POP3D_MAX_CHILD=50
-
-# POP3D_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
-# after this it will commit suicide
-POP3D_CHILD_MAX_CONNECTS=10000
-
-# POP3D_CHILD_TIMEOUT is the number of seconds before the dbmail-pop3d should shutdown
-# a connection which is being idle.
-POP3D_CHILD_TIMEOUT=300
-
-# POP3D_IP_RESOLVE whether the dbmail-pop3d should resolve IP numbers to DNS names in the log
-# this could make a connection slower since dbmail-pop3d has to wait for a resolve before
-# it's able to continue
-POP3D_IP_RESOLVE=yes
-
-
-################### DBMAIL-IMAPD SETTINGS #####################
-
-# IMAPD_EFFECTIVE_USER is the user that dbmail-imapd will run as 
-# (if dbmail-imapd is run on a port < 1024 dbmail-imapd will have to be started by root)
-IMAPD_EFFECTIVE_USER=nobody
-
-# IMAPD_EFFECTIVE_GROUP is the group that dbmail-imapd will run as
-IMAPD_EFFECTIVE_GROUP=nogroup
-
-# IMAPD_BIND_IP is the ipaddress that the dbmail-imapd has to bind to, * from all addresses.
-IMAPD_BIND_IP=*
-
-# IMAPD_BIND_PORT is the port that the dbmail-imapd has to bind to.
-IMAPD_BIND_PORT=143
-
-# IMAPD_DEFAULT_CHILD is the number of children dbmail-imapd defaultly forks to
-IMAPD_DEFAULT_CHILD=5
-
-# IMAPD_MAX_CHILD is the maximum of children the dbmail-imapd is allowed to fork to
-IMAPD_MAX_CHILD=15
-
-# IMAPD_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
-# after this it will commit suicide
-IMAPD_CHILD_MAX_CONNECTS=1000
-
-# IMAPD_DAEMONIZES denotes wheter the IMAP server should daemonize
-# This should be set to yes in a production environment
-IMAPD_DAEMONIZES=yes
-
-# IMAPD_CHILD_TIMEOUT is the number of seconds before the dbmail-imapd should shutdown
-# a connection which is being idle.
-# For a IMAP4r1 compliant server the minimum of this value is 1800 (30 minutes)
-IMAPD_CHILD_TIMEOUT=3000
-
-
-################### FULL MTA DBMAIL-SMTPD SETTINGS #####################
-
-# SMTPD_EFFECTIVE_USER is the user that dbmail-smtpd will run as 
-# (if dbmail-smtpd is run on a port < 1024 dbmail-smtpd will have to be started by root)
-SMTPD_EFFECTIVE_USER=nobody
-
-# SMTPD_EFFECTIVE_GROUP is the group that dbmail-smtpd will run as
-SMTPD_EFFECTIVE_GROUP=nogroup
-
-# SMTPD_BIND_IP is the ipaddress that the dbmail-smtpd has to bind to, * from all addresses.
-SMTPD_BIND_IP=*
-
-# SMTPD_BIND_PORT is the port that the dbmail-smtpd has to bind to.
-SMTPD_BIND_PORT=25
-
-# SMTPD_DEFAULT_CHILD is the number of children dbmail-smtpd defaultly forks to
-SMTPD_DEFAULT_CHILD=20
-
-# SMTPD_MAX_CHILD is the maximum of children the dbmail-smtpd is allowed to fork to
-SMTPD_MAX_CHILD=30
-
-# SMTPD_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
-# after this it will commit suicide
-SMTPD_CHILD_MAX_CONNECTS=1000
-
-# SMTPD_DAEMONIZES denotes wheter the SMTP server should daemonize
-# This should be set to yes in a production environment
-SMTPD_DAEMONIZES=yes
-
-# SMTPD_CHILD_TIMEOUT is the number of seconds before the dbmail-smtpd should shutdown
-# a connection which is being idle.
-SMTPD_CHILD_TIMEOUT=3000
-
-################### OTHER SETTINGS #####################
-
-# DBMAIL_POP_BEFORE_SMTP enables the POP_BEFORE_SMTP feature. Before you can
-# use this feature you'll need to run sql/pop_before_smtp.sql to create the right
-# tables
-DBMAIL_POP_BEFORE_SMTP=no
-
-DBMAIL_IMAP_BEFORE_SMTP=no
-
-# end of configuration file
-
diff -ru -I Id: -x CVS -N dbmail/dbmail.config dbmail.working/dbmail.config
--- dbmail/dbmail.config	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/dbmail.config	2002-11-12 10:01:12.000000000 +1300
@@ -0,0 +1,172 @@
+#
+# (dbmail.config) CONFIG_FILE value specified in condig.h
+# 
+################### DBMAIL DATABASE SETTINGS ###############
+MAIL_HOST      /tmp
+MAIL_USER      dbmail
+MAIL_PASS      dbmail
+MAIL_PORT      3306
+MAILDATABASE   dbmail_store
+
+AUTH_HOST      /tmp
+AUTH_USER      dbmail
+AUTH_PASS      dbmail
+AUTH_PORT      3306
+USERDATABASE   dbmail_auth
+
+MAIL_HOST_READ       /tmp
+MAIL_USER_READ       dbmail
+MAIL_PASS_READ       dbmail
+MAIL_PORT_READ       3306
+MAILDATABASE_READ    dbmail_store
+
+AUTH_HOST_READ       /tmp
+AUTH_USER_READ       dbmail
+AUTH_PASS_READ       dbmail
+AUTH_PORT_READ       3306
+USERDATABASE_READ    dbmail_auth
+
+################### SYSTEM WIDE SETTINGS #####################
+# TRACE_LEVEL is for debugging purposes
+# level 5 is maximum debugging, level 2 logs normal operations
+TRACE_LEVEL=2
+
+# TRACE_TO_SYSLOG enables tracing messages to SYSLOG 
+# 1 traces to syslog, 0 doesn't
+TRACE_TO_SYSLOG=1
+
+# TRACE_VERBOSE enables tracing messages to STDOUT
+# 1 traces verbose, 0 doesn't
+# You should not use verbose tracing in a production environment
+TRACE_VERBOSE=0
+
+################### DBMAIL-SMTP SETTINGS #####################
+# SENDMAIL is the location of your sendmail executable
+# this is needed for boucing mail
+SENDMAIL=/usr/sbin/sendmail
+
+# DBMAIL_FROM_ADDRESS is the email address where bounces come from 
+# this can ofcourse be a DBMAIL account
+DBMAIL_FROM_ADDRESS=dbmail-bounce@orcon.net.nz
+
+# POSTMASTER is the postmaster's email address (which is used in the bounce messages)
+POSTMASTER=dbmail@dbmail-smtp1.orcon.net.nz
+
+################### DBMAIL-POP3D SETTINGS #####################
+# POP3D_EFFECTIVE_USER is the user that dbmail-pop3d will run as
+# (if dbmail-pop3d is run on a port < 1024 dbmail-pop3d will have to be started by root)
+POP3D_EFFECTIVE_USER=nobody
+
+# POP3D_EFFECTIVE_GROUP is the group that dbmail-pop3d will run as 
+POP3D_EFFECTIVE_GROUP=nogroup
+
+# POP3D_BIND_IP is the ipaddress the dbmail-pop3d server has to bind to, * for all addresses
+POP3D_BIND_IP=*
+
+# POP3D_BIND_PORT is the port number the dbmail-pop3d server has to bind to. 
+POP3D_BIND_PORT=110
+
+# POP3D_DEFAULT_CHILD is the number of children dbmail-pop3d defaultly forks to
+# for busy sites this should be set quite high for best performance.
+# the pop server will always keep this number of childs alive 
+POP3D_DEFAULT_CHILD=10
+
+# POP3D_MAX_CHILD is the maximum of children the dbmail-pop3d is allowed to fork to
+# this is also the maximum concurrent connections
+POP3D_MAX_CHILD=50
+
+# POP3D_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
+# after this it will commit suicide
+POP3D_CHILD_MAX_CONNECTS=1000
+
+# POP3D_CHILD_TIMEOUT is the number of seconds before the dbmail-pop3d should shutdown
+# a connection which is being idle.
+POP3D_CHILD_TIMEOUT=300
+
+# POP3D_IP_RESOLVE whether the dbmail-pop3d should resolve IP numbers to DNS names in the log
+# this could make a connection slower since dbmail-pop3d has to wait for a resolve before
+# it's able to continue
+POP3D_IP_RESOLVE=1      # yes|no (1|0)
+
+
+################### DBMAIL-IMAPD SETTINGS #####################
+
+# IMAPD_EFFECTIVE_USER is the user that dbmail-imapd will run as 
+# (if dbmail-imapd is run on a port < 1024 dbmail-imapd will have to be started by root)
+IMAPD_EFFECTIVE_USER=nobody
+
+# IMAPD_EFFECTIVE_GROUP is the group that dbmail-imapd will run as
+IMAPD_EFFECTIVE_GROUP=nogroup
+
+# IMAPD_BIND_IP is the ipaddress that the dbmail-imapd has to bind to, * from all addresses.
+IMAPD_BIND_IP=*
+
+# IMAPD_BIND_PORT is the port that the dbmail-imapd has to bind to.
+IMAPD_BIND_PORT=143
+
+# IMAPD_DEFAULT_CHILD is the number of children dbmail-imapd defaultly forks to
+IMAPD_DEFAULT_CHILD=10
+
+# IMAPD_MAX_CHILD is the maximum of children the dbmail-imapd is allowed to fork to
+IMAPD_MAX_CHILD=25
+
+# IMAPD_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
+# after this it will commit suicide
+IMAPD_CHILD_MAX_CONNECTS=10
+
+# IMAPD_DAEMONIZES denotes wheter the IMAP server should daemonize
+# This should be set to yes in a production environment
+IMAPD_DAEMONIZES=1      # yes|no (1|0)
+
+# IMAPD_CHILD_TIMEOUT is the number of seconds before the dbmail-imapd should shutdown
+# a connection which is being idle.
+# For a IMAP4r1 compliant server the minimum of this value is 1800 (30 minutes)
+IMAPD_CHILD_TIMEOUT=1800
+
+
+################### FULL MTA DBMAIL-SMTPD SETTINGS #####################
+
+# SMTPD_EFFECTIVE_USER is the user that dbmail-smtpd will run as 
+# (if dbmail-smtpd is run on a port < 1024 dbmail-smtpd will have to be started by root)
+SMTPD_EFFECTIVE_USER=nobody
+
+# SMTPD_EFFECTIVE_GROUP is the group that dbmail-smtpd will run as
+SMTPD_EFFECTIVE_GROUP=nogroup
+
+# SMTPD_BIND_IP is the ipaddress that the dbmail-smtpd has to bind to, * from all addresses.
+SMTPD_BIND_IP=*
+
+# SMTPD_BIND_PORT is the port that the dbmail-smtpd has to bind to.
+SMTPD_BIND_PORT=25
+
+# SMTPD_DEFAULT_CHILD is the number of children dbmail-smtpd defaultly forks to
+SMTPD_DEFAULT_CHILD=20
+
+# SMTPD_MAX_CHILD is the maximum of children the dbmail-smtpd is allowed to fork to
+SMTPD_MAX_CHILD=30
+
+# SMTPD_CHILD_MAX_CONNECTS is the maximum number of connections a default childs makes.
+# after this it will commit suicide
+SMTPD_CHILD_MAX_CONNECTS=1000
+
+# SMTPD_DAEMONIZES denotes wheter the SMTP server should daemonize
+# This should be set to yes in a production environment
+SMTPD_DAEMONIZES=1      # yes|no (1|0)
+
+# SMTPD_CHILD_TIMEOUT is the number of seconds before the dbmail-smtpd should shutdown
+# a connection which is being idle.
+SMTPD_CHILD_TIMEOUT=3000
+
+################### OTHER SETTINGS #####################
+
+# DBMAIL_POP_BEFORE_SMTP enables the POP_BEFORE_SMTP feature. Before you can
+# use this feature you'll need to run sql/pop_before_smtp.sql to create the right
+# tables
+DBMAIL_POP_BEFORE_SMTP=1      # yes|no (1|0)
+
+DBMAIL_IMAP_BEFORE_SMTP=1     # yes|no (1|0)
+
+# AUTO_CREATE_MAILBOX if set, mailboxes are automatically created if
+# they not exist
+AUTO_CREATE_MAILBOX=1         # yes|no (1|0)
+
diff -ru -I Id: -x CVS -N dbmail/forward.c dbmail.working/forward.c
--- dbmail/forward.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/forward.c	2002-11-06 17:33:03.000000000 +1300
@@ -10,6 +10,7 @@
 #include "list.h"
 #include "bounce.h"
 #include "forward.h"
+#include "config.h"
 
 int pipe_forward(FILE *instream, struct list *targets, char *from, char *header, unsigned long databasemessageid)
 {
@@ -39,7 +40,7 @@
   
   totalmem = 0;
 	
-  sendmail = db_get_config_item ("SENDMAIL", CONFIG_MANDATORY);
+  sendmail = get_config_item (SENDMAIL, "SENDMAIL");
   
   trace (TRACE_INFO,"pipe_forward(): delivering to %d "
 	 "external addresses", list_totalnodes(targets));
@@ -274,7 +275,6 @@
       return -1;
     }
 
-  my_free (sendmail);
   my_free (strblock);
   return 0;			
 }
diff -ru -I Id: -x CVS -N dbmail/hash.c dbmail.working/hash.c
--- dbmail/hash.c	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/hash.c	2002-11-06 17:33:03.000000000 +1300
@@ -0,0 +1,284 @@
+/* +++Date last modified: 05-Jul-1997 */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "hash.h"
+
+/*
+** public domain code by Jerry Coffin, with improvements by HenkJan Wolthuis.
+**
+** Tested with Visual C 1.0 and Borland C 3.1.
+** Compiles without warnings, and seems like it should be pretty
+** portable.
+*/
+/*
+** Updated code to use malloc both for keys and values(data).
+** Also I changed the 'hash' function, since it didn't work
+** as I've hoped. / Klas Handel
+*/
+
+/*
+** These are used in freeing a table.  Perhaps I should code up
+** something a little less grungy, but it works, so what the heck.
+*/
+
+static void (*function)(void *) = (void (*)(void *))NULL;
+static hash_table *the_table = NULL;
+
+
+/* Initialize the hash_table to the size asked for.  Allocates space
+** for the correct number of pointers and sets them to NULL.  If it
+** can't allocate sufficient memory, signals error by setting the size
+** of the table to 0.
+*/
+
+hash_table *construct_table(hash_table *table, size_t size)
+{
+      size_t i;
+      bucket **temp;
+
+      table -> size  = size;
+      table -> table = (bucket * *)malloc(sizeof(bucket *) * size);
+      temp = table -> table;
+
+      if ( temp == NULL )
+      {
+            table -> size = 0;
+            return table;
+      }
+
+      for (i=0;i<size;i++)
+            temp[i] = NULL;
+      return table;
+}
+
+
+/*
+** Hashes a string to produce an unsigned short, which should be
+** sufficient for most purposes.
+*/
+
+static unsigned hash(char *string)
+{
+   unsigned hashval;
+   for (hashval = 0; *string != '\0'; string++)
+      hashval = *string + 31 * hashval;
+   
+   return hashval;
+}
+
+/*
+** Insert 'key' into hash table.
+** Returns pointer to old data associated with the key, if any, or
+** NULL if the key wasn't in the table previously.
+*/
+
+void *insert(char *key, void *data, hash_table *table)
+{
+      unsigned val = hash(key) % table->size;
+      bucket *ptr;
+
+      /*
+      ** NULL means this bucket hasn't been used yet.  We'll simply
+      ** allocate space for our new bucket and put our data there, with
+      ** the table pointing at it.
+      */
+
+      if (NULL == (table->table)[val])
+      {
+            (table->table)[val] = (bucket *)malloc(sizeof(bucket));
+            if (NULL==(table->table)[val])
+                  return NULL;
+
+            (table->table)[val] -> key = strdup(key);
+            (table->table)[val] -> next = NULL;
+            (table->table)[val] -> data = strdup(data);
+            return (table->table)[val] -> data;
+      }
+
+      /*
+      ** This spot in the table is already in use.  See if the current string
+      ** has already been inserted, and if so, increment its count.
+      */
+
+      for (ptr = (table->table)[val];NULL != ptr; ptr = ptr -> next)
+            if (0 == strcmp(key, ptr->key))
+            {
+                  void *old_data;
+
+                  old_data = ptr->data;
+                  free(ptr->data);
+                  ptr -> data = strdup(data);
+                  return data;
+            }
+
+      /*
+      ** This key must not be in the table yet.  We'll add it to the head of
+      ** the list at this spot in the hash table.  Speed would be
+      ** slightly improved if the list was kept sorted instead.  In this case,
+      ** this code would be moved into the loop above, and the insertion would
+      ** take place as soon as it was determined that the present key in the
+      ** list was larger than this one.
+      */
+
+      ptr = (bucket *)malloc(sizeof(bucket));
+      if (NULL==ptr)
+            return 0;
+      ptr -> key = strdup(key);
+      ptr -> data = strdup(data);
+      ptr -> next = (table->table)[val];
+      (table->table)[val] = ptr;
+      return data;
+}
+
+
+/*
+** Look up a key and return the associated data.  Returns NULL if
+** the key is not in the table.
+*/
+
+void *lookup(char *key, hash_table *table)
+{
+      unsigned val = hash(key) % table->size;
+      bucket *ptr;
+
+      if (NULL == (table->table)[val])
+            return NULL;
+
+      for ( ptr = (table->table)[val];NULL != ptr; ptr = ptr->next )
+      {
+            if (0 == strcmp(key, ptr -> key ) )
+                  return ptr->data;
+      }
+      return NULL;
+}
+
+/*
+** Delete a key from the hash table and return associated
+** data, or NULL if not present.
+*/
+
+void *del(char *key, hash_table *table)
+{
+      unsigned val = hash(key) % table->size;
+      void *data;
+      bucket *ptr, *last = NULL;
+
+      if (NULL == (table->table)[val])
+            return NULL;
+
+      /*
+      ** Traverse the list, keeping track of the previous node in the list.
+      ** When we find the node to delete, we set the previous node's next
+      ** pointer to point to the node after ourself instead.  We then delete
+      ** the key from the present node, and return a pointer to the data it
+      ** contains.
+      */
+
+      for (last = NULL, ptr = (table->table)[val];
+            NULL != ptr;
+            last = ptr, ptr = ptr->next)
+      {
+            if (0 == strcmp(key, ptr -> key))
+            {
+                  if (last != NULL )
+                  {
+                        data = ptr -> data;
+                        last -> next = ptr -> next;
+                        free(ptr->key);
+                        free(ptr->data);
+                        free(ptr);
+                        return data;
+                  }
+
+                  /*
+                  ** If 'last' still equals NULL, it means that we need to
+                  ** delete the first node in the list. This simply consists
+                  ** of putting our own 'next' pointer in the array holding
+                  ** the head of the list.  We then dispose of the current
+                  ** node as above.
+                  */
+
+                  else
+                  {
+                        data = ptr->data;
+                        (table->table)[val] = ptr->next;
+                        free(ptr->key);
+                        free(ptr->data);
+                        free(ptr);
+                        return data;
+                  }
+            }
+      }
+
+      /*
+      ** If we get here, it means we didn't find the item in the table.
+      ** Signal this by returning NULL.
+      */
+
+      return NULL;
+}
+
+/*
+** free_table iterates the table, calling this repeatedly to free
+** each individual node.  This, in turn, calls one or two other
+** functions - one to free the storage used for the key, the other
+** passes a pointer to the data back to a function defined by the user,
+** process the data as needed.
+*/
+
+static void free_node(char *key, void *data)
+{
+      (void) data;
+
+      if (function)
+            function(del(key,the_table));
+      else  del(key,the_table);
+}
+
+/*
+** Frees a complete table by iterating over it and freeing each node.
+** the second parameter is the address of a function it will call with a
+** pointer to the data associated with each node.  This function is
+** responsible for freeing the data, or doing whatever is needed with
+** it.
+*/
+
+void free_table(hash_table *table, void (*func)(void *))
+{
+      function = func;
+      the_table = table;
+
+      enumerate_table( table, free_node);
+      free(table->table);
+      table->table = NULL;
+      table->size = 0;
+
+      the_table = NULL;
+      function = (void (*)(void *))NULL;
+}
+
+/*
+** Simply invokes the function given as the second parameter for each
+** node in the table, passing it the key and the associated data.
+*/
+
+void enumerate_table( hash_table *table, void (*func)(char *, void *))
+{
+      unsigned i;
+      bucket *temp;
+
+      for (i=0;i<table->size; i++)
+      {
+            if ((table->table)[i] != NULL)
+            {
+                  for (temp = (table->table)[i];
+                        NULL != temp;
+                        temp = temp -> next)
+                  {
+                        func(temp -> key, temp->data);
+                  }
+            }
+      }
+}
diff -ru -I Id: -x CVS -N dbmail/hash.h dbmail.working/hash.h
--- dbmail/hash.h	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/hash.h	2002-11-06 17:33:03.000000000 +1300
@@ -0,0 +1,88 @@
+/* +++Date last modified: 05-Jul-1997 */
+
+#ifndef HASH__H
+#define HASH__H
+
+#include <stddef.h>           /* For size_t     */
+
+/*
+** A hash table consists of an array of these buckets.  Each bucket
+** holds a copy of the key, a pointer to the data associated with the
+** key, and a pointer to the next bucket that collided with this one,
+** if there was one.
+*/
+
+typedef struct bucket {
+    char *key;
+    void *data;
+    struct bucket *next;
+} bucket;
+
+/*
+** This is what you actually declare an instance of to create a table.
+** You then call 'construct_table' with the address of this structure,
+** and a guess at the size of the table.  Note that more nodes than this
+** can be inserted in the table, but performance degrades as this
+** happens.  Performance should still be quite adequate until 2 or 3
+** times as many nodes have been inserted as the table was created with.
+*/
+
+typedef struct hash_table {
+    size_t size;
+    bucket **table;
+} hash_table;
+
+/*
+** This is used to construct the table.  If it doesn't succeed, it sets
+** the table's size to 0, and the pointer to the table to NULL.
+*/
+
+hash_table *construct_table(hash_table *table,size_t size);
+
+/*
+** Inserts a pointer to 'data' in the table, with a copy of 'key' as its
+** key.  Note that this makes a copy of the key, but NOT of the
+** associated data.
+*/
+
+void *insert(char *key,void *data,struct hash_table *table);
+
+/*
+** Returns a pointer to the data associated with a key.  If the key has
+** not been inserted in the table, returns NULL.
+*/
+
+void *lookup(char *key,struct hash_table *table);
+
+/*
+** Deletes an entry from the table.  Returns a pointer to the data that
+** was associated with the key so the calling code can dispose of it
+** properly.
+*/
+
+void *del(char *key,struct hash_table *table);
+
+/*
+** Goes through a hash table and calls the function passed to it
+** for each node that has been inserted.  The function is passed
+** a pointer to the key, and a pointer to the data associated
+** with it.
+*/
+
+void enumerate_table(struct hash_table *table,void (*func)(char *,void *));
+
+/*
+** Frees a hash table.  For each node that was inserted in the table,
+** it calls the function whose address it was passed, with a pointer
+** to the data that was in the table.  The function is expected to
+** free the data.  Typical usage would be:
+** free_table(&table, free);
+** if the data placed in the table was dynamically allocated, or:
+** free_table(&table, NULL);
+** if not.  ( If the parameter passed is NULL, it knows not to call
+** any function with the data. )
+*/
+
+void free_table(hash_table *table, void (*func)(void *));
+
+#endif /* HASH__H */
diff -ru -I Id: -x CVS -N dbmail/imapd.c dbmail.working/imapd.c
--- dbmail/imapd.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/imapd.c	2002-11-08 10:35:00.000000000 +1300
@@ -14,117 +14,65 @@
 #include "debug.h"
 #include "misc.h"
 #include "db.h"
+#include "config.h"
+#include "proctitleutils.h"
 
 #define PNAME "dbmail/imap4"
 
 int imap_before_smtp=0;
 
+void usage(void)
+{
+   puts("\nUsage: dbmail-imapd\n\n");
+}
 
-int main()
+int main(int argc, char *argv[], char **envp)
 {
-  int sock,d;
-  char *newuser,*newgroup,*port,*bindip,*defchld,*maxchld,*daem,*to;
-  char *trace_level,*trace_syslog,*trace_verbose;
-  char *before_smtp,*mc;
-  int new_level = 2, new_trace_syslog = 1, new_trace_verbose = 0, timeout = 0;
-  int max_connects=0;
+  int sock;
+  char *newuser,*newgroup,*port,*bindip;
+  int max_connects, timeout, defchld, maxchld, daem;
 
   /* open logs */
   openlog(PNAME, LOG_PID, LOG_MAIL);
 
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
+
+  init_set_proc_title(argc, argv, envp);
+
+  set_proc_title("%s : %s", PNAME, "Loading config");
+
   /* open db connection */
   if (db_connect() != 0)
     trace(TRACE_FATAL, "IMAPD: cannot connect to dbase\n");
 
   /* read options from config */
-  port   = db_get_config_item("IMAPD_BIND_PORT",CONFIG_MANDATORY);
-  bindip = db_get_config_item("IMAPD_BIND_IP",CONFIG_MANDATORY);
-  defchld = db_get_config_item("IMAPD_DEFAULT_CHILD",CONFIG_MANDATORY);
-  maxchld = db_get_config_item("IMAPD_MAX_CHILD",CONFIG_MANDATORY);
-  daem = db_get_config_item("IMAPD_DAEMONIZES", CONFIG_EMPTY);
-  to =  db_get_config_item("IMAPD_CHILD_TIMEOUT", CONFIG_EMPTY);
-  mc = db_get_config_item("IMAPD_CHILD_MAX_CONNECTS",CONFIG_EMPTY);
-
-  before_smtp = db_get_config_item("DBMAIL_IMAP_BEFORE_SMTP", CONFIG_EMPTY);
-  if (before_smtp && strcasecmp(before_smtp,"yes") == 0)
-    {
-      imap_before_smtp = 1;
-      my_free(before_smtp);
-      before_smtp = NULL;
-    }
-
-  trace_level = db_get_config_item("TRACE_LEVEL", CONFIG_EMPTY);
-  trace_syslog = db_get_config_item("TRACE_TO_SYSLOG", CONFIG_EMPTY);
-  trace_verbose = db_get_config_item("TRACE_VERBOSE", CONFIG_EMPTY);
-
-  if (!port || !bindip)
-    trace(TRACE_FATAL, "IMAPD: port and/or ip not specified in configuration file!\r\n");
-
-  if (!defchld || !maxchld)
-    trace(TRACE_FATAL, "IMAPD: default/maximum number of children not "
-	  "specified in configuration file!\r\n");
-
-  if (daem)
-    {
-      d = (strcmp(daem, "yes") == 0);
-      my_free(daem);
-      daem = NULL;
-    }
-  else
-    d = 0;
+  port   = get_config_item(IMAPD_BIND_PORT, "IMAPD_BIND_PORT");
+  bindip = get_config_item(IMAPD_BIND_IP, "IMAPD_BIND_IP");
+  defchld = get_config_item_int(IMAPD_DEFAULT_CHILD, "IMAPD_DEFAULT_CHILD");
+  maxchld = get_config_item_int(IMAPD_MAX_CHILD, "IMAPD_MAX_CHILD");
+  daem = get_config_item_int(IMAPD_DAEMONIZES, "IMAPD_DAEMONIZES");
+  timeout =  get_config_item_int(IMAPD_CHILD_TIMEOUT, "IMAPD_CHILD_TIMEOUT");
+  max_connects = get_config_item_int(IMAPD_CHILD_MAX_CONNECTS, 
+                                     "IMAPD_CHILD_MAX_CONNECTS");
 
-  if (to)
-    {
-      timeout = atoi(to);
-      my_free(to);
-      to = NULL;
-    }
-  
-  if (mc)
-    {
-      max_connects = atoi(mc);
-      my_free(mc);
-      mc = NULL;
-    }
+  imap_before_smtp = get_config_item_int(DBMAIL_IMAP_BEFORE_SMTP, 
+                                    "DBMAIL_IMAP_BEFORE_SMTP");
 
   if (max_connects <= 1)
     {
       max_connects = SS_DEF_MAXCONNECTS;
     }
 
-  if (trace_level)
-    {
-      new_level = atoi(trace_level);
-      my_free(trace_level);
-      trace_level = NULL;
-    }
-
-  if (trace_syslog)
-    {
-      new_trace_syslog = atoi(trace_syslog);
-      my_free(trace_syslog);
-      trace_syslog = NULL;
-    }
-
-  if (trace_verbose)
-    {
-      new_trace_verbose = atoi(trace_verbose);
-      my_free(trace_verbose);
-      trace_verbose = NULL;
-    }
-
-  configure_debug(new_level, new_trace_syslog, new_trace_verbose);
-
-  
   /* open socket */
-  sock = SS_MakeServerSock(bindip, port, atoi(defchld), atoi(maxchld), timeout,
+  sock = SS_MakeServerSock(bindip, port, defchld, maxchld, timeout,
 			   IMAP_TIMEOUT_MSG);
 
-  my_free(port);
-  my_free(bindip);
-  port = NULL;
-  bindip = NULL;
-
   if (sock == -1)
     {
       db_disconnect();
@@ -133,18 +81,13 @@
     }
   
   /* drop priviledges */
-  newuser = db_get_config_item("IMAPD_EFFECTIVE_USER",CONFIG_MANDATORY);
-  newgroup = db_get_config_item("IMAPD_EFFECTIVE_GROUP",CONFIG_MANDATORY);
+  newuser = get_config_item(IMAPD_EFFECTIVE_USER, "IMAPD_EFFECTIVE_USER");
+  newgroup = get_config_item(IMAPD_EFFECTIVE_GROUP, "IMAPD_EFFECTIVE_GROUP");
 
   if ((newuser!=NULL) && (newgroup!=NULL))
   {
     if (drop_priviledges (newuser, newgroup) != 0)
       trace(TRACE_FATAL,"IMAPD: could not set uid %s, gid %s\n",newuser,newgroup);
-    
-    my_free(newuser);
-    my_free(newgroup);
-    newuser = NULL;
-    newgroup = NULL;
   }
   else
     {
@@ -156,7 +99,7 @@
 
   /* get started */
   trace(TRACE_MESSAGE, "IMAPD: server ready to run\n");
-  if (SS_WaitAndProcess(sock, atoi(defchld), atoi(maxchld), d, max_connects,
+  if (SS_WaitAndProcess(sock, defchld, maxchld, daem, max_connects,
 			imap_process, imap_login, imap_error_cleanup) == -1)
     {
       trace(TRACE_FATAL,"IMAPD: Fatal error while processing clients: %s\n",SS_GetErrorMsg());
@@ -165,11 +108,6 @@
 
   SS_CloseServer(sock);
 
-  my_free(defchld);
-  my_free(maxchld);
-  defchld = NULL;
-  maxchld = NULL;
-
   return 0; 
 }
 
diff -ru -I Id: -x CVS -N dbmail/injector.c dbmail.working/injector.c
--- dbmail/injector.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/injector.c	2002-11-07 11:33:51.000000000 +1300
@@ -8,6 +8,7 @@
 #include "db.h"
 #include "debug.h"
 #include "list.h"
+#include "config.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -42,6 +43,14 @@
 int send_quotum_bounce(const char *bouncepath, const char *sendmail, const char *postmaster, const char *fromaddr);
 
 
+void usage(void)
+{
+   puts("\nUsage: dbmail-smtp-injector -n [headerfield]   for normal deliveries\n\
+                                                (default: \"deliver-to\" header)\n\
+       dbmail-smtp-injector -m \"mailbox\" -u [username] for delivery to mailbox (name)\n\
+       dbmail-smtp-injector -d [addresses]  for delivery without using scanner\n\
+       dbmail-smtp-injector -u [usernames]  for direct delivery to users\n\n");
+}
 
 int main(int argc, char *argv[])
 {
@@ -60,7 +69,14 @@
   struct element *el;
 
   openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
-  configure_debug(TRACE_ERROR, 1, 0);  /* do not spill time on reading settings */
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
 
   list_init(&userids);
   list_init(&bounces);
@@ -69,12 +85,8 @@
   /* check command-line options */
   if (argc < 2)
     {
-      printf ("\nUsage: %s -n [headerfield]   for normal deliveries "
-	      "(default: \"deliver-to\" header)\n",argv[0]);
-      printf ("       %s -m \"mailbox\" -u [username] for delivery to mailbox (name)\n"
-              ,argv[0]);
-      printf ("       %s -d [addresses]  for delivery without using scanner\n",argv[0]);
-      printf ("       %s -u [usernames]  for direct delivery to users\n\n",argv[0]);
+      config_usage();
+      usage();
       return 0;
     }
 
@@ -110,9 +122,9 @@
     }
 
   /* get sending utility */
-  sendmail = db_get_config_item ("SENDMAIL", CONFIG_MANDATORY);
-  postmaster = db_get_config_item ("POSTMASTER", CONFIG_MANDATORY);
-  fromaddr = db_get_config_item ("DBMAIL_FROM_ADDRESS", CONFIG_MANDATORY);
+  sendmail = get_config_item (SENDMAIL, "SENDMAIL");
+  postmaster = get_config_item (POSTMASTER, "POSTMASTER");
+  fromaddr = get_config_item (DBMAIL_FROM_ADDRESS, "DBMAIL_FROM_ADDRESS");
 
   if (!sendmail || !postmaster || !fromaddr)
     {
diff -ru -I Id: -x CVS -N dbmail/main.c dbmail.working/main.c
--- dbmail/main.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/main.c	2002-11-07 11:33:51.000000000 +1300
@@ -25,10 +25,18 @@
   
 char *header = NULL;
 char *deliver_to_mailbox = NULL;
-char *trace_level = NULL, *trace_syslog = NULL, *trace_verbose = NULL;
-int new_level = 2, new_trace_syslog = 1, new_trace_verbose = 0;
 u64_t headersize;
 
+
+void usage(void)
+{
+   puts("\nUsage: dbmail-smtp -n [headerfield]   for normal deliveries\n\
+                                                (default: \"deliver-to\" header)\n\
+       dbmail-smtp -m \"mailbox\" -u [username] for delivery to mailbox (name)\n\
+       dbmail-smtp -d [addresses]  for delivery without using scanner\n\
+       dbmail-smtp -u [usernames]  for direct delivery to users\n\n");
+}
+
 int main (int argc, char *argv[]) 
 {
   struct list returnpath; /* returnpath (should aways be just 1 hop */
@@ -37,15 +45,19 @@
 
   openlog(PNAME, LOG_PID, LOG_MAIL);
 
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
+
   /* first check for commandline options */
   if (argc<2)
     {
-      printf ("\nUsage: %s -n [headerfield]   for normal deliveries "
-	      "(default: \"deliver-to\" header)\n",argv[0]);
-      printf ("       %s -m \"mailbox\" -u [username] for delivery to mailbox (name)\n"
-              ,argv[0]);
-      printf ("       %s -d [addresses]  for delivery without using scanner\n",argv[0]);
-      printf ("       %s -u [usernames]  for direct delivery to users\n\n",argv[0]);
+      config_usage();
+      usage();
       return 0;
     }
 
@@ -60,33 +72,6 @@
     }
   /* reading settings */
   
-/*  trace_level = db_get_config_item("TRACE_LEVEL", CONFIG_EMPTY);
-  trace_syslog = db_get_config_item("TRACE_TO_SYSLOG", CONFIG_EMPTY);
-  trace_verbose = db_get_config_item("TRACE_VERBOSE", CONFIG_EMPTY);
-
-  if (trace_level)
-    {
-      new_level = atoi(trace_level);
-      my_free(trace_level);
-      trace_level = NULL;
-    }
-
-  if (trace_syslog)
-    {
-      new_trace_syslog = atoi(trace_syslog);
-      my_free(trace_syslog);
-      trace_syslog = NULL;
-    }
-
-  if (trace_verbose)
-    {
-      new_trace_verbose = atoi(trace_verbose);
-      my_free(trace_verbose);
-      trace_verbose = NULL;
-    }
-*/
-  
-  configure_debug(new_level, new_trace_syslog, new_trace_verbose);
   list_init(&users);
   list_init(&mimelist);
 
diff -ru -I Id: -x CVS -N dbmail/maintenance.c dbmail.working/maintenance.c
--- dbmail/maintenance.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/maintenance.c	2002-11-07 15:21:10.000000000 +1300
@@ -15,11 +15,19 @@
 #include <stdlib.h>
 #include "config.h"
 #include "list.h"
-#include "debug.h"
 #include <time.h>
 
 void find_time(char *timestr, const char *timespec);
 
+void usage(void)
+{
+   puts("\n\
+Usage:  dbmail-maintenance -[cfiphdl]\n\
+\n\
+   dbmail maintenance utility\n\
+   Performs maintenance tasks on the dbmail-databases\n\
+   See the man page for more info\n\n");
+}
 
 int main(int argc, char *argv[])
 {
@@ -31,8 +39,6 @@
   time_t start,stop;
 
   char timespec[LEN],timestr[LEN];
-  char *trace_level,*trace_syslog,*trace_verbose;
-  int new_level = 2, new_trace_syslog = 1, new_trace_verbose = 0;
 
   int opt;
   struct list lostlist;
@@ -43,7 +49,15 @@
   u64_t messages_set_to_delete;
     
   openlog(PNAME, LOG_PID, LOG_MAIL);
-	
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
+
   setvbuf(stdout,0,_IONBF,0);
   printf ("*** dbmail-maintenance ***\n");
 	
@@ -102,10 +116,8 @@
 
   if (show_help)
     {
-      printf("\ndbmail maintenance utility\n\n");
-      printf("Performs maintenance tasks on the dbmail-databases\n");
-      printf("Use: dbmail-maintenance -[cfiphdl]\n");
-      printf("See the man page for more info\n\n");
+      config_usage();
+      usage();
       return 0;
     }
 
@@ -117,7 +129,7 @@
       return 0;
     }
 
-  printf ("Opening connection to the database... ");
+  printf ("Opening connection to the message database... ");
 
   if (db_connect()==-1)
     {
@@ -127,34 +139,6 @@
 
   printf ("Ok. Connected\n");
 
-	
-  trace_level = db_get_config_item("TRACE_LEVEL", CONFIG_EMPTY);
-  trace_syslog = db_get_config_item("TRACE_TO_SYSLOG", CONFIG_EMPTY);
-  trace_verbose = db_get_config_item("TRACE_VERBOSE", CONFIG_EMPTY);
-
-  if (trace_level)
-    {
-      new_level = atoi(trace_level);
-      my_free(trace_level);
-      trace_level = NULL;
-    }
-
-  if (trace_syslog)
-    {
-      new_trace_syslog = atoi(trace_syslog);
-      my_free(trace_syslog);
-      trace_syslog = NULL;
-    }
-
-  if (trace_verbose)
-    {
-      new_trace_verbose = atoi(trace_verbose);
-      my_free(trace_verbose);
-      trace_verbose = NULL;
-    }
-
-  configure_debug(new_level, new_trace_syslog, new_trace_verbose);
-
   if (purge_deleted)
     {
       printf ("Deleting messages with DELETE status... ");
diff -ru -I Id: -x CVS -N dbmail/pipe.c dbmail.working/pipe.c
--- dbmail/pipe.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/pipe.c	2002-11-08 13:26:44.000000000 +1300
@@ -224,11 +224,11 @@
           userid = auth_user_exists((char*)tmp->data);
           if (userid == -1)
           {
-              trace(TRACE_ERROR,"insert_messages(): dbase error checking user [%s]", (char*)tmp->data);
+              trace(TRACE_FATAL,"insert_messages(): dbase error checking user [%s]", (char*)tmp->data);
           }
           else if (userid == 0)
           {
-              trace(TRACE_ERROR,"insert_messages(): user [%s] does not exist", (char*)tmp->data);
+              trace(TRACE_FATAL,"insert_messages(): user [%s] does not exist", (char*)tmp->data);
           }
           else
           {
diff -ru -I Id: -x CVS -N dbmail/pop3.c dbmail.working/pop3.c
--- dbmail/pop3.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/pop3.c	2002-11-12 11:42:54.000000000 +1300
@@ -10,6 +10,10 @@
 #include "dbmailtypes.h"
 #include "auth.h"
 
+#include "proctitleutils.h"
+
+#define PNAME "dbmail/pop3d"
+
 /* max_errors defines the maximum number of allowed failures */
 #define MAX_ERRORS 3
 /* max_in_buffer defines the maximum number of bytes that are allowed to be 
@@ -63,6 +67,9 @@
   char *command, *value;
   int cmdtype, found=0;
   int indx=0;
+#ifdef STRIPREALM
+  int i=0;
+#endif
   u64_t result;
   u64_t top_lines, top_messageid;
   struct element *tmpelement;
@@ -122,6 +129,7 @@
     case POP3_QUIT :
       {
 	fprintf ((FILE *)stream, "+OK see ya later\r\n");
+	set_proc_title("%s : %s", PNAME, "Idle");
 	return 0;
       }
     case POP3_USER : 
@@ -142,6 +150,15 @@
 	    strncpy (username,value,strlen(value)+1);
 	  }
 
+#ifdef STRIPREALM
+	while (i < (strlen(value)+1)) { 
+		if (value[i] == '@') { 
+			username[i]='\0';
+		}
+		i++;
+	}	
+#endif
+
 	fprintf ((FILE *)stream, "+OK Password required for %s\r\n",username);
 	return 1;
       }
@@ -201,6 +218,9 @@
 			username, curr_session.virtual_totalmessages,
 			curr_session.virtual_totalsize);
 		}
+
+		set_proc_title("%s : USER %s", PNAME, username);
+
 	      return result;
 	    }
 	  }
@@ -493,7 +513,8 @@
       {
 	if (state!=AUTHORIZATION)
 	  return pop3_error(stream,"-ERR wrong command mode, sir\r\n");
-	fprintf  ((FILE *)stream, "+OK List of supported mechanisms\r\n.\r\n");
+	//fprintf  ((FILE *)stream, "+OK List of supported mechanisms\r\n.\r\n");
+	fprintf  ((FILE *)stream, "-ERR AUTH not supported\r\n");
 	return 1;
       }
 
diff -ru -I Id: -x CVS -N dbmail/pop3.h dbmail.working/pop3.h
--- dbmail/pop3.h	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/pop3.h	2002-11-07 11:23:09.000000000 +1300
@@ -96,3 +96,5 @@
 int pop3 (void *stream, char *buffer);
 
 #endif
+
+void setproctitle(const char *fmt, ...);
diff -ru -I Id: -x CVS -N dbmail/pop3d.c dbmail.working/pop3d.c
--- dbmail/pop3d.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/pop3d.c	2002-11-12 11:42:54.000000000 +1300
@@ -8,7 +8,9 @@
 #include "db.h"
 #include "debug.h"
 #include "auth.h"
+#include "config.h"
 #include <errno.h>
+#include "proctitleutils.h"
 
 #define INCOMING_BUFFER_SIZE 512
 #define IP_ADDR_MAXSIZE 16
@@ -400,7 +402,12 @@
 }
 
 
-int main (int argc, char *argv[])
+void usage(void)
+{
+   puts("\nUsage: dbmail-pop3d\n\n");
+}
+
+int main (int argc, char *argv[], char **envp)
 {
   struct sockaddr_in adr_srvr;
   struct sockaddr_in adr_clnt;
@@ -410,10 +417,6 @@
   char *newuser, *newgroup;
   
   char *ipaddr, *port;
-
-  char *trace_level=NULL,*trace_syslog=NULL,*trace_verbose=NULL;
-  int new_level = 2, new_trace_syslog = 1, new_trace_verbose = 0;
-  char *resolve_setting=NULL, *before_smtp=NULL, *max_connects=0;
   
   pid_t childpid = 0;
 
@@ -427,78 +430,35 @@
 
   /* open logs */
   openlog(PNAME, LOG_PID, LOG_MAIL);
-  
-  /* connect to the database */
-  if (db_connect()< 0) 
-    trace(TRACE_FATAL,"main(): could not connect to database"); 
-	
-  /* debug settings */
-  trace_level = db_get_config_item("TRACE_LEVEL", CONFIG_EMPTY);
-  trace_syslog = db_get_config_item("TRACE_TO_SYSLOG", CONFIG_EMPTY);
-  trace_verbose = db_get_config_item("TRACE_VERBOSE", CONFIG_EMPTY);
-  timeout_setting = db_get_config_item("POP3D_CHILD_TIMEOUT", CONFIG_EMPTY);
-  resolve_setting = db_get_config_item("POP3D_IP_RESOLVE",CONFIG_EMPTY);
-
-  before_smtp = db_get_config_item("DBMAIL_POP_BEFORE_SMTP",CONFIG_EMPTY);
-  if (before_smtp && strcasecmp(before_smtp,"yes") == 0)
-    {
-      pop_before_smtp = 1;
-      my_free(before_smtp);
-      before_smtp = NULL;
-    }
 
-  if (resolve_setting)
-  {
-    if (strcasecmp(resolve_setting,"yes")==0)
-      resolve_client = 1;
-    else
-      resolve_client = 0;
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
 
-    my_free(resolve_setting);
-    resolve_setting = NULL;
-  }	
-  
-  if (timeout_setting) 
-  {
-    server_timeout = atoi(timeout_setting);
-    my_free (timeout_setting);
-    if (server_timeout<10)
-      trace (TRACE_STOP,"main(): POP3D_CHILD_TIMEOUT setting is insane [%d]",
-	     server_timeout);
-    timeout_setting = NULL;
-  }
-  else
-    server_timeout = DEFAULT_SERVER_TIMEOUT;
-  
-  if (trace_level)
-    {
-      new_level = atoi(trace_level);
-      my_free(trace_level);
-      trace_level = NULL;
-    }
-
-  if (trace_syslog)
-    {
-      new_trace_syslog = atoi(trace_syslog);
-      my_free(trace_syslog);
-      trace_syslog = NULL;
-    }
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
 
-  if (trace_verbose)
-    {
-      new_trace_verbose = atoi(trace_verbose);
-      my_free(trace_verbose);
-      trace_verbose = NULL;
-    }
+  init_set_proc_title(argc, argv, envp);
 
-  configure_debug(new_level, new_trace_syslog, new_trace_verbose);
+  set_proc_title("%s : %s", PNAME, "Loading config");
 
+  /* connect to the database */
+  if (db_connect()< 0) 
+    trace(TRACE_FATAL,"main(): could not connect to database"); 
+	
+  server_timeout = get_config_item_int(POP3D_CHILD_TIMEOUT, "POP3D_CHILD_TIMEOUT");
+  resolve_client = get_config_item_int(POP3D_IP_RESOLVE, "POP3D_IP_RESOLVE");
+  pop_before_smtp = get_config_item_int(DBMAIL_POP_BEFORE_SMTP, "DBMAIL_POP_BEFORE_SMTP");
+  
+  if (server_timeout<10)
+    trace (TRACE_STOP,"main(): POP3D_CHILD_TIMEOUT setting is insane [%d]", server_timeout);
 
+  
   /* daemonize */
   if (fork ())
     exit (0);
 		
-  
   close (fileno(stdin));
   close (fileno(stdout));
   close (fileno(stderr)); 
@@ -534,8 +494,8 @@
   if (s == -1 ) 
     trace (TRACE_FATAL,"main(): call socket(2) failed");
 
-  ipaddr = db_get_config_item("POP3D_BIND_IP",CONFIG_MANDATORY); 
-  port = db_get_config_item("POP3D_BIND_PORT",CONFIG_MANDATORY);
+  ipaddr = get_config_item(POP3D_BIND_IP, "POP3D_BIND_IP");
+  port = get_config_item(POP3D_BIND_PORT, "POP3D_BIND_PORT");
 
 
   if (ipaddr != NULL)
@@ -572,33 +532,22 @@
   trace (TRACE_MESSAGE,"main(): Dropping priviledges");		
 
 	
-  newuser = db_get_config_item("POP3D_EFFECTIVE_USER",CONFIG_MANDATORY);
-  newgroup = db_get_config_item("POP3D_EFFECTIVE_GROUP",CONFIG_MANDATORY);
+  newuser = get_config_item(POP3D_EFFECTIVE_USER, "POP3D_EFFECTIVE_USER");
+  newgroup = get_config_item(POP3D_EFFECTIVE_GROUP, "POP3D_EFFECTIVE_GROUP");
 	
   if ((newuser!=NULL) && (newgroup!=NULL))
   {
     if (drop_priviledges (newuser, newgroup) != 0)
       trace (TRACE_FATAL,"main(): could not set uid %s, gid %s",newuser,newgroup);
-    
-    my_free(newuser);
-    my_free(newgroup);
-    newuser = NULL;
-    newgroup = NULL;
   }
   else
     trace(TRACE_FATAL,"main(): newuser and newgroup should not be NULL");
 
   /* get child config */
-  defchld = atoi(db_get_config_item("POP3D_DEFAULT_CHILD",CONFIG_MANDATORY));
-  maxchld = atoi(db_get_config_item("POP3D_MAX_CHILD",CONFIG_MANDATORY));
+  defchld = get_config_item_int(POP3D_DEFAULT_CHILD, "POP3D_DEFAULT_CHILD");
+  maxchld = get_config_item_int(POP3D_MAX_CHILD, "POP3D_MAX_CHILD");
 
-  max_connects = db_get_config_item("POP3D_CHILD_MAX_CONNECTS",CONFIG_EMPTY);
-  if (max_connects)
-    {
-      n_max_connects = atoi(max_connects);
-      my_free(max_connects);
-      max_connects = 0;
-    }
+  n_max_connects = get_config_item_int(POP3D_CHILD_MAX_CONNECTS, "POP3D_CHILD_MAX_CONNECTS");
 
   if (n_max_connects <= 1)
     n_max_connects = POP3_DEF_MAXCONNECT;
@@ -679,11 +628,13 @@
     {
       /* split up in the 'server' part and the client part */
 
+  set_proc_title("%s : %s", PNAME, "Server process");
       /* 
        * Client loop 
        */
       if (getpid() != server_pid)
 	{
+  	  set_proc_title("%s : %s", PNAME, "Idle");
 	  for (;;)
 	    {
 	      /* wait for a connection */
@@ -701,7 +652,9 @@
 	      (*default_children)++;		
 	      n_connects++;
 
-	      handle_client(myhostname, c, adr_clnt);
+	      set_proc_title("%s : %s", PNAME, "Login state");
+		   handle_client(myhostname, c, adr_clnt);
+	      set_proc_title("%s : %s", PNAME, "Idle");
 		
 	      (*default_children)--;
 
diff -ru -I Id: -x CVS -N dbmail/imap4.c dbmail.working/imap4.c
--- dbmail/imap4.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/imap4.c	2002-11-12 10:01:12.000000000 +1300
@@ -19,6 +19,8 @@
 #include "db.h"
 #include "auth.h"
 
+#define PNAME "dbmail/imap4"
+
 #define MAX_LINESIZE 4096
 #define COMMAND_SHOW_LEVEL TRACE_ERROR
 
@@ -37,7 +39,7 @@
 "!@#$%^&+()-=_`~[]{}\\|'\" ;:,.<>/? ";
 
 const char AcceptedMailboxnameChars[] = 
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=/ _";
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=/ _.";
 
 const char *IMAP_COMMANDS[] = 
 {
@@ -122,6 +124,7 @@
   char *tag = NULL,*cpy,**args,*command;
   int i,done,result;
   int nfaultyresponses;
+  int endidx;
   imap_userdata_t *ud = ci->userData;
   mailbox_t newmailbox;
 
@@ -168,6 +171,8 @@
 	{
 	  /* we have had just about it with this user */
 	  sleep(2); /* avoid DOS attacks */
+	  
+	  trace(COMMAND_SHOW_LEVEL,"FATAL: To many fault responses\n");
 	  fprintf(ci->tx,"* BYE [TRY RFC]\r\n");
 	  done = 1;
 	  break;
@@ -234,6 +239,13 @@
 	  return 1;
 	}
 
+	  /* Hack by Mark Mackay to get lines of '^M' only to be ignored... */
+	  endidx = strlen(line)-1;
+	  if (line >= 0 && endidx ==1 && (line[endidx] == '\n' ||line[endidx] == '\r')) 
+	{
+	  continue;
+	}
+
       /* clarify data a little */
       clarify_data(line);
 
@@ -327,7 +339,6 @@
 	  /* update mailbox info */
 	  memset(&newmailbox, 0, sizeof(newmailbox));
 	  newmailbox.uid = ud->mailbox.uid;
-
 	  result = db_getmailbox(&newmailbox, ud->userid);
 	  if (result == -1)
 	    {
diff -ru -I Id: -x CVS -N dbmail/imapcommands.c dbmail.working/imapcommands.c
--- dbmail/imapcommands.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/imapcommands.c	2002-11-12 11:42:54.000000000 +1300
@@ -20,6 +20,9 @@
 #include <sys/types.h>
 #include <time.h>
 #include "debug.h"
+#include "proctitleutils.h"
+
+#define PNAME "dbmail/imap4"
 
 #ifndef MAX_LINESIZE
 #define MAX_LINESIZE 1024
@@ -117,6 +120,8 @@
 
   trace(TRACE_MESSAGE, "IMAPD [PID %d]: user (id:%d) logging out @ %s\r\n",getpid(),
 	ud->userid,timestr);
+  
+  set_proc_title("%s : Idle", PNAME);
 
   fprintf(ci->tx,"* BYE dbmail imap server kisses you goodbye\r\n");
 
@@ -176,6 +181,8 @@
   trace(TRACE_MESSAGE, "IMAPD [PID %d]: user (id %llu, name %s) login accepted @ %s\r\n",(int)getpid(),
 	userid,args[0],timestr);
 
+  set_proc_title("%s : USER: %s [%s]", PNAME, args[0], ci->ip);
+
   /* update client info */
   ud->userid = userid;
   ud->state = IMAPCS_AUTHENTICATED;
diff -ru -I Id: -x CVS -N dbmail/proctitleutils.c dbmail.working/proctitleutils.c
--- dbmail/proctitleutils.c	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/proctitleutils.c	2002-11-12 13:58:48.000000000 +1300
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "proctitleutils.h"
+
+/* Globals */
+static char **Argv = ((void *)0);
+extern char *__progname, *__progname_full;
+static char *LastArgv = ((void *)0);
+
+void init_set_proc_title(int argc, char *argv[], char *envp[])
+{
+  int i, envpsize;
+  extern char **environ;
+  char **p;
+  char *ptr;
+
+  for(i = envpsize = 0; envp[i] != NULL; i++)
+    envpsize += strlen(envp[i]) + 1;
+  
+  if((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL ) {
+    environ = p;
+
+    for(i = 0; envp[i] != NULL; i++) {
+      if((environ[i] = malloc(strlen(envp[i]) + 1)) != NULL)
+	strcpy(environ[i], envp[i]);
+    }
+    
+    environ[i] = NULL;
+  }
+
+  Argv = argv;
+    
+  for(i = 0; envp[i] != NULL; i++) {
+    if((LastArgv + 1) == envp[i]) // Not sure if this conditional is needed
+      LastArgv = envp[i] + strlen(envp[i]);
+  }
+
+  // Clear the title (from the start of argv to the start of envp)
+  // All command line arguments should have been taken care of by now...
+  for(ptr=Argv[0]; ptr<envp[0]; ptr++)
+    *ptr='\0';
+
+// Pretty sure you don't need this either
+  __progname = strdup("proftpd");
+  __progname_full = strdup(argv[0]);
+}
+
+void set_proc_title(char *fmt,...)
+{
+  va_list msg;
+  static char statbuf[8192];
+  char *p = Argv[0];
+  int maxlen = (LastArgv - Argv[0]) - 2;
+
+  // Clear old Argv[0]
+  for(;*p; p++)
+    *p='\0';
+   
+  va_start(msg,fmt);
+
+  memset(statbuf, 0, sizeof(statbuf));
+  vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
+
+  va_end(msg);
+
+  snprintf(Argv[0], maxlen, "%s", statbuf);
+  
+  Argv[1] = ((void *)0) ;
+}
+
+
diff -ru -I Id: -x CVS -N dbmail/proctitleutils.h dbmail.working/proctitleutils.h
--- dbmail/proctitleutils.h	1970-01-01 12:00:00.000000000 +1200
+++ dbmail.working/proctitleutils.h	2002-11-07 11:23:09.000000000 +1300
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+
+void set_proc_title(char *fmt,...);
+void init_set_proc_title(int argc, char *argv[], char *envp[]);
diff -ru -I Id: -x CVS -N dbmail/raw-convert.c dbmail.working/raw-convert.c
--- dbmail/raw-convert.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/raw-convert.c	2002-11-07 11:33:51.000000000 +1300
@@ -25,6 +25,7 @@
 #include "db.h"
 #include "dbmailtypes.h"
 #include "debug.h"
+#include "config.h"
 #include <regex.h>
 
 #define MAX_LINESIZE 1024
@@ -87,6 +88,10 @@
 int create_remaining_users();
 
 
+void usage(void)
+{
+   puts("\nUsage: raw-convertor <starting directory> <pwd file> <# lines in pwd file>\n\n");
+}
 
 int main (int argc, char* argv[])
 {
@@ -95,14 +100,22 @@
   int result,i;
   char q[1024];
 
+  openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
   if (argc < 4)
     {
-      printf ("Usage: %s <starting directory> <pwd file> <# lines in pwd file>\n", argv[0]);
+      config_usage();
+      usage();
       return -1;
     }
 
-  openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
-  configure_debug(TRACE_ERROR, 1, 0);
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
 
   if (init_files() != 0)
     {
diff -ru -I Id: -x CVS -N dbmail/serverservice.c dbmail.working/serverservice.c
--- dbmail/serverservice.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/serverservice.c	2002-11-12 11:42:54.000000000 +1300
@@ -26,8 +26,10 @@
 #include <signal.h>
 #include "serverservice.h"
 #include "debug.h"
+#include "proctitleutils.h"
 
 #define LOG_USERS 1
+#define PNAME "dbmail/imap4"
 
 /* error data */
 #define SS_ERROR_MSG_LEN 100
@@ -297,6 +299,8 @@
 	trace(TRACE_INFO,"   %d\n", default_child_pids[i]);
     }
 
+  set_proc_title("%s : %s", PNAME, "Idle");
+
   for ( ;; )
     {
       /* this infinite loop is needed for killed default-children:
@@ -356,6 +360,7 @@
 		    csock, inet_ntoa(saClient.sin_addr));
 #endif
 
+	      set_proc_title("%s : %s", PNAME, "Login");
 	      if ((*Login)(&client) == SS_LOGIN_OK)
 		{
 		  client.loginStatus = SS_LOGIN_OK; /* xtra, should have been set by Login() */
@@ -370,6 +375,7 @@
 	      
 		  close(csock);
 	  
+	      set_proc_title("%s : %s", PNAME, "Login failure");
 #if LOG_USERS > 0
 		  trace(TRACE_MESSAGE,"SS_WaitAndProcess(): client @ socket %d (IP: %s) "
 			"login refused, connection closed\n",
@@ -386,7 +392,9 @@
 		    *ss_n_default_children_used);
 
 	      /* handle client */
+	      set_proc_title("%s : %s", PNAME, "Logged in");
 	      (*ClientHandler)(&client); 
+	      set_proc_title("%s : %s", PNAME, "Idle");
 	      alarm(0);           /* remove any installed timeout-alarms */
 
 #if LOG_USERS > 0
@@ -429,6 +437,8 @@
 	{
 	  /* this is the server process */
 
+  set_proc_title("%s : %s", PNAME, "Server process");
+
 	  for (;;)
 	    {
 	      /* check if default-child have died 
@@ -556,6 +566,7 @@
 			csock, inet_ntoa(saClient.sin_addr));
 #endif
 
+	      set_proc_title("%s : %s", PNAME, "Login");
 		  if ((*Login)(&client) == SS_LOGIN_OK)
 		    {
 		      client.loginStatus = SS_LOGIN_OK; /* xtra, should have been set by Login() */
@@ -567,6 +578,7 @@
 		      fclose(client.tx);
 		      close(csock);
 	  
+	      set_proc_title("%s : %s", PNAME, "Login failure");
 #if LOG_USERS > 0
 		      trace(TRACE_MESSAGE,"SS_WaitAndProcess(): client @ socket %d (IP: %s) "
 			    "login refused, connection closed\n",
@@ -580,7 +592,9 @@
 		  client.ip[SS_IPNUM_LEN - 1] = '\0';
 
 		  /* handle client */
-		  (*ClientHandler)(&client); 
+        set_proc_title("%s : %s", PNAME, "Login state");
+        (*ClientHandler)(&client); 
+        set_proc_title("%s : %s", PNAME, "Idle");
 		  alarm(0);                   /* remove any installed timeout-alarms */
 
 #if LOG_USERS > 0
@@ -658,6 +672,7 @@
 
 	}
 
+      set_proc_title("%s : %s", PNAME, "Cleanup client");
       (*the_client_cleanup)(&client);
       memset(&client, 0, sizeof(client));
 
@@ -697,6 +712,7 @@
 	  fclose(client.rx);
 	}
 
+      set_proc_title("%s : %s", PNAME, "Cleanup client");
       (*the_client_cleanup)(&client);
       memset(&client, 0, sizeof(client));
     }
diff -ru -I Id: -x CVS -N dbmail/settings.c dbmail.working/settings.c
--- dbmail/settings.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/settings.c	2002-11-07 11:33:51.000000000 +1300
@@ -16,6 +16,10 @@
   FILE *configfile;
   char *readbuf, *field, *val,*fname;
   int i;
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, NULL);
 	
   readbuf = (char *)malloc(LINE_BUFFER_SIZE);
 	
diff -ru -I Id: -x CVS -N dbmail/uni-one-convert.c dbmail.working/uni-one-convert.c
--- dbmail/uni-one-convert.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/uni-one-convert.c	2002-11-08 13:26:44.000000000 +1300
@@ -14,6 +14,7 @@
 #include "auth.h"
 #include "dbmailtypes.h"
 #include "debug.h"
+#include "config.h"
 #include <regex.h>
 
 #define MAX_LINESIZE 1024
@@ -29,7 +30,10 @@
 int traverse (char *path);
 int process_mboxfile(char *file, u64_t userid);
 
-
+void usage(void)
+{
+   puts("\nUsage: uni-one-convertor <dir>\n\n");
+}
 
 int main (int argc, char* argv[])
 {
@@ -37,14 +41,23 @@
   time_t stop;
   int result;
 
+  openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, usage);
+
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
+
   if (argc < 2)
     {
-      printf ("Error, traverse need a directory as argument\n");
+      config_usage();
+      usage();
       return -1;
     }
 
-  openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
-  configure_debug(TRACE_ERROR, 1, 0);
 
   /* open dbase connections */
   if (db_connect() != 0 || auth_connect() != 0)
@@ -139,7 +152,7 @@
   regex_t preg;
   int result;
   FILE *infile;
-  int in_msg, header_passed;
+  int in_msg, header_passed=0;
   char newunique[UID_SIZE];
   unsigned cnt,len,newlines;
   u64_t msgid=0, size;
diff -ru -I Id: -x CVS -N dbmail/user.c dbmail.working/user.c
--- dbmail/user.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/user.c	2002-11-07 11:33:51.000000000 +1300
@@ -16,6 +16,7 @@
 #include <crypt.h>
 #include <time.h>
 #include <stdarg.h>
+#include "config.h"
 
 #define SHADOWFILE "/etc/shadow"
 char *getToken(char** str,const char* delims);
@@ -49,7 +50,15 @@
   int argidx = 0;
 
   openlog(PNAME, LOG_PID, LOG_MAIL);
+
+  // Init configuration parameters. init_config only looks at parameters
+  // starting with '--'.
+  init_config(&argc, argv, show_help);
 	
+  configure_debug(get_config_item_int(TRACE_LEVEL, "TRACE_LEVEL"), 
+                  get_config_item_int(TRACE_TO_SYSLOG, "TRACE_TO_SYSLOG"), 
+                  get_config_item_int(TRACE_VERBOSE, "TRACE_VERBOSE"));
+                  
   setvbuf(stdout,0,_IONBF,0);
 	
   if (argc<2)
@@ -88,7 +97,6 @@
     }
 	
   quiet_printf ("Ok. Connected\n");
-  configure_debug(TRACE_ERROR, 1, 0);
   
   switch (argv[argidx+1][0])
     {
@@ -260,7 +268,7 @@
 
 int do_change(int argc, char *argv[])
 {
-  int i,result, retval=0;
+  int i,result=0, retval=0;
   u64_t newsize,userid,newcid;
   char *endptr,*entry,*passwdfile;
   char pw[50]="";
@@ -615,8 +623,8 @@
   FILE *passfile = NULL;
   char pass_char[512];
   int pass_size = 511;
-  char *pw;
-  char *user;
+  char *pw = NULL;
+  char *user = NULL;
 
   if ((passfile = fopen(filename, "r")) == NULL)
     return NULL;
diff -ru -I Id: -x CVS -N dbmail/vut2dbmail.c dbmail.working/vut2dbmail.c
--- dbmail/vut2dbmail.c	2002-11-13 11:21:07.000000000 +1300
+++ dbmail.working/vut2dbmail.c	2002-11-06 17:33:03.000000000 +1300
@@ -11,6 +11,7 @@
 #include <ctype.h>
 #include "db.h"
 #include "auth.h"
+#include "config.h"
 
 #define MAXLINESIZE 1024
 #define DEF_MAXMAILSIZE 1024
