diff --git a/ChangeLog b/ChangeLog
index 39150c3173f13cfb8a21fb5fc763c959c70f49e1..22dd99c84fa492f010825f1d1de19467c8abe82c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2006-02-01  Per Cederqvist  <ceder@lysator.liu.se>
 
+	Configuration cleanup: use constructor/destructor semantics.
+	* src/server/conf-file.h (struct datatype): Replaced the freer
+	attribute with ctor and dtor attributes.  All users updated.
+	Added some documentation.
+	(free_config): New function.
+	* src/server/conf-file.c (init_init): Call the constructors for
+	all parameters.
+	(free_config): New function, that calls the destructors for all
+	parameters.
+	(ctor_string): New static function. 
+	(dtor_string): New static function, which replaces
+	unassign_string.
+	(assign_string): Expect the object to already be constructed.
+	(unassign_string): Removed.
+	(cf_string): Use ctor_string and dtor_string.
+	* src/server/server-config.c (cf_log_param): Updated for new
+	struct datatype.
+	(cf_jubel): Ditto.
+	(cf_ident_param): Ditto.
+	(free_configuration): Use free_config to do the work.
+
 	Namespace cleanup.
 	* src/server/conf-file.c: Moved all struct datatype objects to the
 	end of the file, to avoid having to forward-declare all of the
diff --git a/src/server/conf-file.c b/src/server/conf-file.c
index b57852918d0254ede16716acdd59e6f7ffc18041..c4f0da49f47ad0a9631a94329ce557bc94ba3a89 100644
--- a/src/server/conf-file.c
+++ b/src/server/conf-file.c
@@ -72,7 +72,8 @@ init_init(const struct parameter *par)
     int ix;
 
     for (npar = 0; par[npar].name != NULL; npar++)
-      ;
+	if (par[npar].tp->ctor != NULL)
+	    par[npar].tp->ctor(&par[npar]);
 
     assert (assignment_count == NULL);
     assignment_count = smalloc(npar * sizeof (*assignment_count));
@@ -240,6 +241,17 @@ read_config(const char *config_file,
 	return OK;
 }
 
+void
+free_config(const struct parameter *par)
+{
+    int i;
+
+    for (i = 0; par[i].name != NULL; ++i)
+        if (par[i].tp->dtor != NULL)
+            (*par[i].tp->dtor)(&par[i]);
+}
+
+
 static Success
 assign_text_no(const char *val, 
 	       const struct parameter *par)
@@ -323,10 +335,29 @@ assign_uint(const char *val,
     return OK;
 }
 
+static void
+ctor_string(const struct parameter *par)
+{
+    *(char**)par->value = NULL;
+}
+
+static void
+dtor_string(const struct parameter *par)
+{
+    if (*(char**)par->value != NULL)
+    {
+	sfree(*(char**)par->value);
+	*(char**)par->value = NULL;
+    }
+}
+
 static Success
 assign_string(const char *val, 
 	      const struct parameter *par)
 {
+    if (*(char**)par->value != NULL)
+	sfree(*(char**)par->value);
+
     if (val == NULL)
 	*(char**)par->value = NULL;
     else
@@ -489,49 +520,38 @@ assign_timeval(const char *val,
 }
 
 
-static void
-unassign_string(const struct parameter *par)
-{
-    if (*(char**)par->value != NULL)
-    {
-        sfree(*(char**)par->value);
-        *(char**)par->value = NULL;
-    }
-}
-
-
 const struct datatype cf_text_no = {
-    assign_text_no, NULL,
+    assign_text_no, NULL, NULL,
 };
 
 const struct datatype cf_conf_no = {
-    assign_conf_no, NULL
+    assign_conf_no, NULL, NULL,
 };
 
 const struct datatype cf_int = {
-    assign_int, NULL
+    assign_int, NULL, NULL,
 };
 
 const struct datatype cf_ulong = {
-    assign_ulong, NULL
+    assign_ulong, NULL, NULL,
 };
 
 const struct datatype cf_uint = {
-    assign_uint, NULL
+    assign_uint, NULL, NULL,
 };
 
 const struct datatype cf_string = {
-    assign_string, unassign_string
+    assign_string, ctor_string, dtor_string,
 };
 
 const struct datatype cf_bool = {
-    assign_bool, NULL
+    assign_bool, NULL, NULL,
 };
 
 const struct datatype cf_double = {
-    assign_double, NULL
+    assign_double, NULL, NULL,
 };
 
 const struct datatype cf_timeval = {
-    assign_timeval, NULL
+    assign_timeval, NULL, NULL,
 };
diff --git a/src/server/conf-file.h b/src/server/conf-file.h
index b15c3fed587cbf13e370d489099eb4390295b78e..b7c183c3e13590437b10b4c8ade358fb9b74fac7 100644
--- a/src/server/conf-file.h
+++ b/src/server/conf-file.h
@@ -32,8 +32,18 @@
 struct parameter;
 
 struct datatype {
+    /* Assign a value to the parameter pointed to by par.  The value
+       comes from the val. */
     Success (*assigner)(const char *val, const struct parameter *par);
-    void    (*freer)(const struct parameter *par);
+
+    /* Constructor: initialize the parameter pointed to by par.  May
+       allocate memory.  However, the memory pointed to by par must
+       already be allocated.   NULL if no construction is needed. */
+    void    (*ctor)(const struct parameter *par);
+
+    /* Destructor: undo whatever the constructor did.  NULL if no
+       destruction is needed. */
+    void    (*dtor)(const struct parameter *par);
 };
 
 struct parameter {
@@ -48,6 +58,7 @@ struct parameter {
 };
 
 Success read_config(const char *config_file, const struct parameter *par);
+void free_config(const struct parameter *par);
 
 extern const struct datatype cf_text_no;
 extern const struct datatype cf_conf_no;
diff --git a/src/server/server-config.c b/src/server/server-config.c
index 1ac8a236179ab339a8f450653c1da4bb23fa013a..1de5201bcd8538f3a98ecb18c4c6224288fcdb38 100644
--- a/src/server/server-config.c
+++ b/src/server/server-config.c
@@ -75,15 +75,15 @@ static Success jubel(const char *val, const struct parameter *par);
 static Success ident_param(const char *val, const struct parameter *par);
 
 static const struct datatype cf_log_param = {
-    log_param, NULL,
+    log_param, NULL, NULL,
 };
 
 static const struct datatype cf_jubel = {
-    jubel, NULL,
+    jubel, NULL, NULL,
 };
 
 static const struct datatype cf_ident_param = {
-    ident_param, NULL,
+    ident_param, NULL, NULL,
 };
 
     
@@ -894,16 +894,7 @@ read_configuration(const char *conf_file)
 void
 free_configuration(void)
 {
-    int i = 0;
-
-    while (parameters[i].name != NULL)
-    {
-        if (parameters[i].tp->freer != NULL)
-        {
-            (*parameters[i].tp->freer)(&parameters[i]);
-        }
-        i += 1;
-    }
+    free_config(parameters);
 }
 
 #ifdef DEBUG_CALLS