* released 1.2.4
* merged Alexander Lazic's and Klaus Wagner's work on application
  cookie-based persistence. Since this is the first merge, this version is
  not intended for general use and reports are more than welcome. Some
  documentation is really needed though.
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000..364ed14
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,228 @@
+/*
+  This File is copied from
+  
+  http://www.oreilly.com/catalog/masteralgoc/index.html
+  Mastering Algorithms with C
+  By Kyle Loudon
+  ISBN: 1-56592-453-3
+  Publishd by O'Reilly
+  
+ */
+
+/*****************************************************************************
+ *                                                                            *
+ *  -------------------------------- list.c --------------------------------  *
+ *                                                                            *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <include/list.h>
+
+/*****************************************************************************
+*                                                                            *
+*  ------------------------------- list_init ------------------------------  *
+*                                                                            *
+*****************************************************************************/
+
+void list_init(List *list, void (*destroy)(void *data)) {
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Initialize the list.                                                      *
+   *                                                                            *
+   *****************************************************************************/
+
+  list->size = 0;
+  list->destroy = destroy;
+  list->head = NULL;
+  list->tail = NULL;
+  return;
+} /* end list_init() */
+
+/*****************************************************************************
+ *                                                                            *
+ *  ----------------------------- list_destroy -----------------------------  *
+ *                                                                            *
+ *****************************************************************************/
+
+void list_destroy(List *list) {
+
+  void               *data;
+  int rc; 
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Remove each element.                                                      *
+   *                                                                            *
+   *****************************************************************************/
+
+  while (list_size(list) > 0) {
+    
+    rc = list_rem_next(list, NULL, (void **)&data);
+    
+    if (( rc == 0) && (list->destroy != NULL)) { 
+
+      /***********************************************************************
+       *                                                                      *
+       *  Call a user-defined function to free dynamically allocated data.    *
+       *                                                                      *
+       ***********************************************************************/
+
+      list->destroy(data);
+    }/* end if() */
+  }/* end while() */
+
+  /*****************************************************************************
+   *                                                                            *
+   *  No operations are allowed now, but clear the structure as a precaution.   *
+   *                                                                            *
+   *****************************************************************************/
+
+  memset(list, 0, sizeof(List));
+  return;
+} /* void list_destroy(List *list) */
+
+/*****************************************************************************
+ *                                                                            *
+ *  ----------------------------- list_ins_next ----------------------------  *
+ *                                                                            *
+ *****************************************************************************/
+
+int list_ins_next(List *list, ListElmt *element, const void *data) {
+
+  ListElmt           *new_element;
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Allocate storage for the element.                                         *
+   *                                                                            *
+   *****************************************************************************/
+
+  if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
+    return -1;
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Insert the element into the list.                                         *
+   *                                                                            *
+   *****************************************************************************/
+
+  new_element->data = (void *)data;
+
+  if (element == NULL) {
+
+    /**************************************************************************
+     *                                                                         *
+     *  Handle insertion at the head of the list.                              *
+     *                                                                         *
+     **************************************************************************/
+
+    if (list_size(list) == 0)
+      list->tail = new_element;
+
+    new_element->next = list->head;
+    list->head = new_element;
+  }/* end if (element == NULL) */
+  else {
+
+    /**************************************************************************
+     *                                                                         *
+     *  Handle insertion somewhere other than at the head.                     *
+     *                                                                         *
+     **************************************************************************/
+
+    if (element->next == NULL)
+      list->tail = new_element;
+
+    new_element->next = element->next;
+    element->next = new_element;
+  }/* end else */
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Adjust the size of the list to account for the inserted element.          *
+   *                                                                            *
+   *****************************************************************************/
+
+  list->size++;
+  return 0;
+} /* end list_ins_next() */
+
+/*****************************************************************************
+ *                                                                            *
+ *  ----------------------------- list_rem_next ----------------------------  *
+ *                                                                            *
+ *****************************************************************************/
+
+int list_rem_next(List *list, ListElmt *element, void **data) {
+
+  ListElmt           *old_element;
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Do not allow removal from an empty list.                                  *
+   *                                                                            *
+   *****************************************************************************/
+
+  if (list_size(list) == 0)
+    return -1;
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Remove the element from the list.                                         *
+   *                                                                            *
+   *****************************************************************************/
+
+  if (element == NULL) {
+
+    /**************************************************************************
+     *                                                                         *
+     *  Handle removal from the head of the list.                              *
+     *                                                                         *
+     **************************************************************************/
+
+    *data = list->head->data;
+    old_element = list->head;
+    list->head = list->head->next;
+
+    if (list_size(list) == 1)
+      list->tail = NULL;
+  }/* end if (element == NULL) */
+  else {
+
+    /**************************************************************************
+     *                                                                         *
+     *  Handle removal from somewhere other than the head.                     *
+     *                                                                         *
+     **************************************************************************/
+
+    if (element->next == NULL)
+      return -1;
+
+    *data = element->next->data;
+    old_element = element->next;
+    element->next = element->next->next;
+
+    if (element->next == NULL)
+      list->tail = element;
+  }/* end else */
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Free the storage allocated by the abstract data type.                     *
+   *                                                                            *
+   *****************************************************************************/
+
+  free(old_element);
+
+  /*****************************************************************************
+   *                                                                            *
+   *  Adjust the size of the list to account for the removed element.           *
+   *                                                                            *
+   *****************************************************************************/
+
+  list->size--;
+  return 0;
+}