diff -Naur 3.3/doc/efun/sl_close 3.3sqlite/doc/efun/sl_close
--- 3.3/doc/efun/sl_close	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun/sl_close	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,13 @@
+OPTIONAL
+SYNOPSIS
+        void sl_close()
+
+DESCRIPTION
+        Closes the SQLite database that is associated with the
+        current object.
+
+        The function is available only if the driver is compiled with
+        SQLite support. In that case, __SQLITE__ is defined.
+
+SEE ALSO
+        sl_open, sl_exec, sl_insert_id
diff -Naur 3.3/doc/efun/sl_exec 3.3sqlite/doc/efun/sl_exec
--- 3.3/doc/efun/sl_exec	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun/sl_exec	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,21 @@
+OPTIONAL
+SYNOPSIS
+        mixed* sl_exec(string statement, ...)
+
+DESCRIPTION
+        Executes the SQL statement <statement> for the current
+        SQLite database. The SQL statement may contain wildcards like
+        '?' and '?nnn', where 'nnn' is an integer. These wildcards
+        can be given as further parameters to sl_exec. With '?nnn'
+        the number of a specific parameter can be given, the first
+        parameter has number 1.
+
+        If the statement returns data, sl_exec returns an array
+        with each row (which is itself an array of columns) as 
+        an element.
+
+        The function is available only if the driver is compiled with
+        SQLite support. In that case, __SQLITE__ is defined.
+
+SEE ALSO
+        sl_open, sl_insert_id, sl_close
diff -Naur 3.3/doc/efun/sl_insert_id 3.3sqlite/doc/efun/sl_insert_id
--- 3.3/doc/efun/sl_insert_id	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun/sl_insert_id	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,14 @@
+OPTIONAL
+SYNOPSIS
+        int sl_insert_id()
+
+DESCRIPTION
+        After inserting a line into a table with an AUTO_INCREMENT field,
+        this efun can be used to return the (new) value of the AUTO_INCREMENT
+        field.
+
+        The function is available only if the driver is compiled with
+        SQLite support. In that case, __SQLITE__ is defined.
+
+SEE ALSO
+        sl_open, sl_exec, sl_close
diff -Naur 3.3/doc/efun/sl_open 3.3sqlite/doc/efun/sl_open
--- 3.3/doc/efun/sl_open	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun/sl_open	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,15 @@
+OPTIONAL
+SYNOPSIS
+        int sl_open(string filename)
+
+DESCRIPTION
+        Opens the file <filename> for use as a SQLite database.
+        If the file doesn't exists it will be created.
+        Only one open file per object is allowed. On success this
+        function returns 1, otherwise usually an error is thrown.
+
+        The function is available only if the driver is compiled with
+        SQLite support. In that case, __SQLITE__ is defined.
+
+SEE ALSO
+        sl_exec, sl_insert_id, sl_close
diff -Naur 3.3/doc/efun.de/sl_close.de 3.3sqlite/doc/efun.de/sl_close.de
--- 3.3/doc/efun.de/sl_close.de	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun.de/sl_close.de	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,14 @@
+OPTIONAL
+SYNOPSIS
+        void sl_close()
+
+BESCHREIBUNG
+        Schliesst die SQLite-Datenbank, welche vom aktuellen Objekt
+        geoeffnet wurde.
+
+        Diese Funktion ist nur verfuegbar, wenn der Driver mit SQLite-
+        Unterstuetzung compiliert wurde. In diesem Fall ist das Makro
+        __SQLITE__ definiert.
+
+SIEHE AUCH
+        sl_open, sl_exec, sl_insert_id
diff -Naur 3.3/doc/efun.de/sl_exec.de 3.3sqlite/doc/efun.de/sl_exec.de
--- 3.3/doc/efun.de/sl_exec.de	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun.de/sl_exec.de	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,22 @@
+OPTIONAL
+SYNOPSIS
+        mixed* sl_exec(string statement, ...)
+
+BESCHREIBUNG
+        Fuehrt den SQL-Befehl <statement> in der aktuell geoeffneten
+        SQLite-Datenbank aus. Dieser SQL-Befehl kann Wildcards wie '?'
+        nd '?nnn', wobei 'nnn' eine Zahl ist, enthalten. Diese Wildcards
+        koennen als weitere Parameter an sl_exec uebergeben werden.
+        Mit '?nnn' kann direkt die Nummer eines bestimmten Parameters
+        angegeben werden, der erste Parameter hat die Nummer 1.
+
+        Falls der SQL-Befehl Daten zurueckliefert, liefert sl_exec ein
+        Array aus den einzelnen Zeilen (welche wieder Arrays der einzelnen
+        Felder sind) zurueck.
+
+        Diese Funktion ist nur verfuegbar, wenn der Driver mit SQLite-
+        Unterstuetzung compiliert wurde. In diesem Fall ist das Makro
+        __SQLITE__ definiert.
+
+SIEHE AUCH
+        sl_open, sl_insert_id, sl_close
diff -Naur 3.3/doc/efun.de/sl_insert_id.de 3.3sqlite/doc/efun.de/sl_insert_id.de
--- 3.3/doc/efun.de/sl_insert_id.de	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun.de/sl_insert_id.de	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,15 @@
+OPTIONAL
+SYNOPSIS
+        int sl_insert_id()
+
+BESCHREIBUNG
+        Nachdem eine Zeile in eine Tabelle mit einer AUTO_INCREMENT-Spalte
+        eingefuegt wurde, kann man mit dieser Funktion den (neuen) Wert
+        dieses AUTO_INCREMENT-Feldes der eingefuegten Zeile abfragen.
+
+        Diese Funktion ist nur verfuegbar, wenn der Driver mit SQLite-
+        Unterstuetzung compiliert wurde. In diesem Fall ist das Makro
+        __SQLITE__ definiert.
+
+SIEHE AUCH
+        sl_open, sl_exec, sl_close
diff -Naur 3.3/doc/efun.de/sl_open.de 3.3sqlite/doc/efun.de/sl_open.de
--- 3.3/doc/efun.de/sl_open.de	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/doc/efun.de/sl_open.de	2005-12-06 00:06:06.000000000 +0100
@@ -0,0 +1,17 @@
+OPTIONAL
+SYNOPSIS
+        int sl_open(string filename)
+
+BESCHREIBUNG
+        Oeffnet die Datei <filename> als SQLite-Datenbank. Falls
+        sie noch nicht existiert, wird sie erstellt. Es ist nur
+        eine geoeffnete Datenbank pro Objekt erlaubt. Im Erfolgsfalle
+        liefert diese Funktion 1 zurueck, anderenfalls wird
+        normalerweise ein Fehler ausgeloest.
+
+        Diese Funktion ist nur verfuegbar, wenn der Driver mit SQLite-
+        Unterstuetzung compiliert wurde. In diesem Fall ist das Makro
+        __SQLITE__ definiert.
+
+SIEHE AUCH
+        sl_exec, sl_insert_id, sl_close
diff -Naur 3.3/src/autoconf/acconfig.h 3.3sqlite/src/autoconf/acconfig.h
--- 3.3/src/autoconf/acconfig.h	2005-06-22 14:51:58.000000000 +0200
+++ 3.3sqlite/src/autoconf/acconfig.h	2005-12-05 22:45:32.000000000 +0100
@@ -99,6 +99,12 @@
 /* Does the machine offer PostgreSQL? */
 #undef HAS_PGSQL
 
+/* Does the machine offer SQLite3? */
+#undef HAS_SQLITE3
+
+/* Does SQLite3 use pthreads? */
+#undef SQLITE3_USES_PTHREADS
+
 /* Does the machine offer GnuTLS? */
 #undef HAS_GNUTLS
 #undef HAS_GNUTLS_VERSION
diff -Naur 3.3/src/autoconf/configure.in 3.3sqlite/src/autoconf/configure.in
--- 3.3/src/autoconf/configure.in	2005-11-08 08:31:42.000000000 +0100
+++ 3.3sqlite/src/autoconf/configure.in	2005-12-06 00:01:36.000000000 +0100
@@ -120,6 +120,7 @@
 AC_MY_ARG_ENABLE(use-mccp,no,,[Enables MCCP support])
 AC_MY_ARG_ENABLE(use-mysql,no,,[Enables mySQL support])
 AC_MY_ARG_ENABLE(use-pgsql,no,,[Enables PostgreSQL support])
+AC_MY_ARG_ENABLE(use-sqlite3,no,,[Enables SQLite3 support])
 AC_MY_ARG_ENABLE(use-pthreads,no,,[enable using of threads for socket writes])
 AC_MY_ARG_ENABLE(use-pcre,yes,,[Enables PCRE: no/yes/builtin/no-builtin])
 AC_MY_ARG_ENABLE(use-deprecated,yes,,[Enables obsolete and deprecated efuns])
@@ -305,6 +306,20 @@
   enable_use_pgsql="yes"
 fi
 
+AC_UPDATE_VAR(enable_use_sqlite3)
+if test "x$enable_use_sqlite3" = "x" || test "x$enable_use_sqlite3" = "xyes"; then
+  cdef_use_sqlite3="#define"
+  sqlite3_path=
+  enable_use_sqlite3="yes"
+elif test "x$enable_use_sqlite3" = "xno"; then
+  cdef_use_sqlite3="#undef"
+  sqlite3_path=
+else
+  cdef_use_sqlite3="#define"
+  sqlite3_path="$enable_use_sqlite3"
+  enable_use_sqlite3="yes"
+fi
+
 AC_UPDATE_VAR(enable_use_tls)
 if test "x$enable_use_tls" = "x" || test "x$enable_use_tls" = "xyes"; then
   cdef_use_tls="#define"
@@ -1505,6 +1520,129 @@
   fi
 fi
 
+# ---
+
+# --- SQLite3 ---
+
+AC_CACHE_CHECK(for SQLite3,lp_cv_has_sqlite3,
+for TESTPATH in "" "$sqlite3_path" "$sqlite3_path/include" "/usr/local/sqlite3/include" "/usr/local/include/sqlite3" "/usr/include/sqlite3" "/usr/lib/sqlite3" "/usr/local/include"; do
+    saveflags="$CFLAGS"
+    if test "x$TESTPATH" != "x"; then
+        CFLAGS="$saveflags -I$TESTPATH"
+    fi
+AC_TRY_COMPILE([
+#include <sqlite3.h>
+
+sqlite3 * foo(void)
+{
+    static sqlite3 * var;
+    
+    return var;
+}
+],,
+lp_cv_has_sqlite3=yes
+if test "x$TESTPATH" != "x"; then
+    EXTRA_CFLAGS="-I$TESTPATH $EXTRA_CFLAGS"
+fi
+break;
+,
+lp_cv_has_sqlite3=no
+CFLAGS="$saveflags"
+)
+done
+)
+
+# The system has the include files - now search for the libraries.
+if test $lp_cv_has_sqlite3 = yes; then
+  saveflags="$CFLAGS"
+  AC_DEFINE(HAS_SQLITE3)
+
+  if test $enable_use_sqlite3 = yes; then
+    tmp=""
+
+
+    if test "x$sqlite3_path" = "x"; then
+        AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -lsqlite3")
+        if test "x$tmp" = "x"; then
+            if test -d "/usr/local/sqlite3/lib/sqlite3"; then
+                unset ac_cv_lib_sqlite3_main
+                CFLAGS="$saveflags -L/usr/local/sqlite3/lib/sqlite3"
+                AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/sqlite3/lib/sqlite3 -lsqlite3")
+            elif test -d "/usr/local/sqlite3/lib"; then
+                unset ac_cv_lib_sqlite3_main
+                CFLAGS="$saveflags -L/usr/local/sqlite3/lib"
+                AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/sqlite3/lib -lsqlite3")
+            elif test -d "/usr/local/lib"; then
+                unset ac_cv_lib_sqlite3_main
+                CFLAGS="$saveflags -L/usr/local/lib"
+                AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/lib -lsqlite3")
+            elif test -d "/usr/lib/sqlite3/lib"; then
+                unset ac_cv_lib_sqlite3_main
+                CFLAGS="$saveflags -L/usr/lib/sqlite3/lib"
+                AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/lib/sqlite3/lib -lsqlite3")
+            fi
+        fi
+    else
+        if test -d "${sqlite3_path}/lib/sqlite3"; then
+            CFLAGS="$saveflags -L${sqlite3_path}/lib/sqlite3"
+            AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L${sqlite3_path}/lib/sqlite3 -lsqlite3")
+        elif test -d "${sqlite3_path}/lib"; then
+            CFLAGS="$saveflags -L${sqlite3_path}/lib"
+            AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L${sqlite3_path}/lib -lsqlite3")
+        elif test -d "${sqlite3_path}"; then
+            CFLAGS="$saveflags -L$sqlite3_path"
+            AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L$sqlite3_path -lsqlite3")
+        fi
+    fi
+
+    if test "x$tmp" = "x"; then
+        unset ac_cv_lib_sqlite3_main
+        if test -d "/usr/local/sqlite3/lib"; then
+            CFLAGS="$saveflags -L/usr/local/sqlite3/lib"
+            AC_CHECK_LIB(sqlite3,main, tmp="$PKGLIBS -L/usr/local/sqlite3/lib -lsqlite3")
+        fi
+    fi
+
+    if test "x$tmp" == "x"; then
+        echo "libsqlite3 library not found - disabling SQLite3 support"
+        AC_NOT_AVAILABLE(use-sqlite3)
+        cdef_use_sqlite3="#undef"
+        enable_use_sqlite3="no"
+        sqlite3_path=
+        lp_cv_has_sqlite3="no"
+    else
+        PKGLIBS="$tmp"
+    fi
+  fi
+
+  if test $enable_use_sqlite3 = yes; then
+      savelibs="$LIBS"
+      LIBS="$LIBS $PKGLIBS"
+      
+      # Check if it uses pthreads
+
+      AC_CHECK_LIB(sqlite3, pthread_create,
+      	   lp_cv_sqlite3_uses_pthreads=yes,
+      	   lp_cv_sqlite3_uses_pthreads=no
+      )
+
+      if test $lp_cv_sqlite3_uses_pthreads = yes ; then
+           AC_DEFINE(SQLITE3_USES_PTHREADS)
+      fi
+
+      LIBS="$savelibs"
+  fi
+
+  CFLAGS="$saveflags"
+else
+  if test $enable_use_sqlite3 = yes; then
+      AC_NOT_AVAILABLE(use-sqlite3)
+      cdef_use_sqlite3="#undef"
+      enable_use_sqlite3=no
+  fi
+fi
+# ---
+
 # --- Check if we need zlib libraries for mccp ---
 
 if test "x$enable_use_mccp" = "x" || test "x$enable_use_mccp" = "xyes"; then
@@ -2506,6 +2644,7 @@
 AC_SUBST(cdef_use_ipv6)
 AC_SUBST(cdef_use_mysql)
 AC_SUBST(cdef_use_pgsql)
+AC_SUBST(cdef_use_sqlite3)
 AC_SUBST(cdef_use_pthreads)
 AC_SUBST(cdef_use_alists)
 AC_SUBST(cdef_use_mccp)
diff -Naur 3.3/src/config.h.in 3.3sqlite/src/config.h.in
--- 3.3/src/config.h.in	2005-06-22 14:52:18.000000000 +0200
+++ 3.3sqlite/src/config.h.in	2005-12-06 00:25:12.000000000 +0100
@@ -348,6 +348,11 @@
  */
 @cdef_use_pgsql@ USE_PGSQL
 
+/* Define this if you want SQLite3 support (assuming that your host
+ * actually offers this.
+ */
+@cdef_use_sqlite3@ USE_SQLITE3
+
 /* Define this if you want alist support.
  */
 @cdef_use_alists@ USE_ALISTS
diff -Naur 3.3/src/func_spec 3.3sqlite/src/func_spec
--- 3.3/src/func_spec	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/func_spec	2005-12-06 00:05:58.000000000 +0100
@@ -722,6 +722,16 @@
 
 #endif /* USE_PGSQL */
 
+
+#ifdef USE_SQLITE3
+
+int      sl_open(string);
+mixed    sl_exec(string, ...);
+int      sl_insert_id();
+void     sl_close();
+
+#endif /* USE_SQLITE3 */
+
 #ifdef USE_TLS
 
 int     tls_query_connection_state(object default: F_THIS_OBJECT);
diff -Naur 3.3/src/lex.c 3.3sqlite/src/lex.c
--- 3.3/src/lex.c	2005-11-08 08:31:45.000000000 +0100
+++ 3.3sqlite/src/lex.c	2005-12-06 00:05:58.000000000 +0100
@@ -824,6 +824,9 @@
 #ifdef USE_MYSQL
     add_permanent_define("__MYSQL__", -1, string_copy("1"), MY_FALSE);
 #endif
+#ifdef USE_SQLITE3
+    add_permanent_define("__SQLITE__", -1, string_copy("1"), MY_FALSE);
+#endif
 #ifdef USE_PGSQL
     add_permanent_define("__PGSQL__", -1, string_copy("1"), MY_FALSE);
 #endif
diff -Naur 3.3/src/main.c 3.3sqlite/src/main.c
--- 3.3/src/main.c	2005-06-22 14:52:18.000000000 +0200
+++ 3.3sqlite/src/main.c	2005-12-06 00:26:50.000000000 +0100
@@ -1792,6 +1792,9 @@
 #ifdef USE_PGSQL
                               , "PostgreSQL supported\n"
 #endif
+#ifdef USE_SQLITE3
+                              , "SQLite3 supported\n"
+#endif
 #ifdef USE_PTHREADS
                               , "PThreads supported\n"
 #endif
diff -Naur 3.3/src/Makefile.in 3.3sqlite/src/Makefile.in
--- 3.3/src/Makefile.in	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/Makefile.in	2005-12-06 00:07:39.000000000 +0100
@@ -90,7 +90,7 @@
       lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
       otable.c\
       parser.c parse.c pkg-alists.c pkg-mccp.c pkg-mysql.c pkg-pcre.c \
-      pkg-pgsql.c pkg-tls.c \
+      pkg-pgsql.c pkg-tls.c pkg-sqlite3.c \
       ptmalloc.c port.c ptrtable.c \
       random.c regexp.c sha1.c simulate.c simul_efun.c stdstrings.c \
       strfuns.c structs.c sprintf.c swap.c wiz_list.c xalloc.c 
@@ -101,7 +101,7 @@
       lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
       otable.o \
       parser.o parse.o pkg-alists.o pkg-mccp.o pkg-mysql.o pkg-pcre.o \
-      pkg-pgsql.o pkg-tls.o \
+      pkg-pgsql.o pkg-tls.o pkg-sqlite3.o \
       ptmalloc.o port.o ptrtable.o \
       random.o regexp.o sha1.o simulate.o simul_efun.o stdstrings.o \
       strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@ 
diff -Naur 3.3/src/object.c 3.3sqlite/src/object.c
--- 3.3/src/object.c	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/object.c	2005-12-06 00:05:58.000000000 +0100
@@ -43,6 +43,7 @@
  *       wiz_list_t    * user;
  *       wiz_list_t    * eff_user;
  *       int             extra_num_variables;  (ifdef DEBUG)
+ *       int             open_sqlite_db (ifdef USE_SQLITE3)
  *       svalue_t      * variables;
  *       unsigned long   ticks, gigaticks;
  *   }
diff -Naur 3.3/src/object.h 3.3sqlite/src/object.h
--- 3.3/src/object.h	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/object.h	2005-12-06 00:05:58.000000000 +0100
@@ -50,6 +50,9 @@
     int extra_num_variables;
     /* amylaar : used to determine where to check ref counts at all... */
 #endif
+#ifdef USE_SQLITE3
+    int open_sqlite_db;   /* does this object have an open sqlite db */
+#endif 
     svalue_t *variables;
       /* All variables to this object: an array of svalues, allocated
        * in a separate block.
diff -Naur 3.3/src/pkg-sqlite3.c 3.3sqlite/src/pkg-sqlite3.c
--- 3.3/src/pkg-sqlite3.c	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/src/pkg-sqlite3.c	2005-12-06 00:07:14.000000000 +0100
@@ -0,0 +1,437 @@
+#include "config.h"
+#ifdef USE_SQLITE3
+  
+#include <sqlite3.h>
+#include "typedefs.h"
+  
+#include "my-alloca.h"
+#include <errno.h>
+#include <stddef.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "array.h"
+#include "interpret.h"
+#include "mstrings.h"
+#include "simulate.h"
+#include "svalue.h"
+#include "xalloc.h"
+#include "object.h"
+#include "stdstrings.h"
+
+typedef struct sqlite_rows_s sqlite_rows_t;
+typedef struct sqlite_dbs_s sqlite_dbs_t;
+
+/* Since we don't know the number of rows while we retrieve the
+ * rows from a query we save the data in a single-linked list first
+ * and move them into an array after the retrieval has finished 
+ */ 
+struct sqlite_rows_s 
+{
+    vector_t * row;
+    sqlite_rows_t * last;
+};
+
+/* This structure is used for error handling. In case of an error
+ * our handler gets called with a pointer to this structure.
+ */
+struct sl_exec_cleanup_s
+{
+    svalue_t head; /* push_error_handler saves the link to our
+                      handler here. */
+
+    sqlite3_stmt *stmt;
+    sqlite_rows_t *rows;
+};
+
+/* Database connections should be bound to the object which opens 
+ * database file. We will store all database connections in a 
+ * linked list. 
+ */ 
+struct sqlite_dbs_s 
+{
+    sqlite3 * db;
+    object_t * obj;
+    sqlite_dbs_t * next;
+    sqlite_dbs_t * prev;
+};
+
+/* The list of database connections.
+ */ 
+static sqlite_dbs_t *head = NULL;
+  
+// HELPER FUNS
+sqlite_dbs_t *find_db (object_t * obj) 
+{
+    sqlite_dbs_t *tmp = head;
+
+    while (tmp)
+    {
+        if (tmp->obj==obj) return tmp;
+        tmp=tmp->prev;
+    }
+    return NULL;
+}
+
+sqlite_dbs_t * new_db()
+{
+    sqlite_dbs_t *tmp;
+    tmp = pxalloc (sizeof (*tmp));
+    if(!tmp) return NULL;
+   
+    tmp->db=NULL;
+    tmp->obj=NULL;
+    tmp->next=NULL;
+    tmp->prev=head;
+    if (head) head->next=tmp;
+    head=tmp;
+   
+    return tmp;
+}
+
+void remove_db(sqlite_dbs_t *db)
+{
+    if (db==head)
+    {
+   	if (head->prev) 
+   	{
+   	    head->prev->next=NULL;
+   	    head=head->prev;
+   	}
+        else
+        {
+   	    head=NULL;
+   	}
+    }
+    else
+    {
+   	if (db->next) db->next->prev=db->prev;
+   	if (db->prev) db->prev->next=db->next;
+    }
+    pfree(db);
+}
+
+static int
+my_sqlite3_authorizer(void* data, int what, const char* arg1, const char* arg2,
+        const char* dbname, const char* view)
+{
+    /* TODO: Check them via privilege_violation resp. valid_write.
+             (Don't know, whether sqlite can handle longjmps out of
+             its code in case of an error...)
+    */
+
+    switch(what)
+    {
+        case SQLITE_PRAGMA:
+	    if(!strcasecmp(arg1, "synchronous"))
+		return SQLITE_OK;
+            return SQLITE_DENY;
+
+        case SQLITE_ATTACH:
+        case SQLITE_DETACH:
+            return SQLITE_DENY;
+	
+        default:
+            return SQLITE_OK;
+    }
+}
+
+// EFUNS GO FROM HERE
+svalue_t * 
+f_sl_open (svalue_t *sp) 
+{
+    string_t *file;
+    sqlite3 *db;
+    sqlite_dbs_t *tmp;
+    int err;
+   
+    file = check_valid_path(sp->u.str, current_object, STR_SQLITE_OPEN , MY_TRUE);
+    if (!file)
+        errorf("Illegal use of sl_open('%s')\n", get_txt(sp->u.str));
+   
+    tmp = find_db (current_object);
+    if (tmp)
+    {
+        free_mstring(file);
+        errorf("The current object already has a database open.\n");
+    }
+
+    err = sqlite3_open (get_txt(file), &db);
+    free_mstring(file);
+    if (err)
+    {
+        const char* msg = sqlite3_errmsg(db);
+        sqlite3_close(db);
+        errorf("sl_open: %s\n", msg );
+        /* NOTREACHED */
+    }
+
+    /* create a new chain link and hang on the old chain */
+    tmp=new_db(); 
+    if(!tmp)
+    {
+        sqlite3_close(db);
+        errorf("(sl_open) Out of memory: (%lu bytes)\n",
+                (unsigned long) sizeof(*tmp));
+    }
+   
+    tmp->db = db;
+    tmp->obj = current_object;
+    current_object->open_sqlite_db=1;
+
+    /* Synchronous is damn slow. Forget it. */
+    sqlite3_exec(db, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
+    sqlite3_set_authorizer(db, my_sqlite3_authorizer, NULL);
+  
+    free_string_svalue (sp);
+    put_number (sp, 1);
+    return sp;
+}
+
+static void
+sl_exec_cleanup (svalue_t * arg)
+{
+    sqlite_rows_t *row;
+    struct sl_exec_cleanup_s * data;
+    
+    data = (struct sl_exec_cleanup_s *)arg;
+    
+    if(data->stmt)
+        sqlite3_finalize(data->stmt);
+
+    row = data->rows;
+    while(row)
+    {
+        sqlite_rows_t *temp;
+
+        if(row->row)
+            free_array(row->row);
+        temp = row;
+        row = row->last;
+        pfree(temp);
+    }
+
+    xfree(data);
+}
+
+svalue_t * 
+v_sl_exec (svalue_t * sp, int num_arg) 
+{
+    svalue_t *argp;
+    sqlite_dbs_t *db;
+    sqlite3_stmt *stmt;
+    const char* tail;
+    int err, rows, cols, num;
+    struct sl_exec_cleanup_s * rec_data;
+    vector_t * result;
+
+    argp = sp - num_arg + 1; /* First argument: the SQL query */
+    
+    db = find_db (current_object);
+    if (!db)
+        errorf("The current object doesn't have a database open.\n");
+
+    err = sqlite3_prepare(db->db, get_txt(argp->u.str), mstrsize(argp->u.str),
+        &stmt, &tail);
+    if(err)
+    {
+        const char* msg = sqlite3_errmsg(db->db);
+        if(stmt)
+            sqlite3_finalize(stmt);
+        errorf("sl_exec: %s\n", msg);
+        /* NOTREACHED */
+    }
+    
+    /* Now bind all parameters. */
+    for(argp++, num=1; argp <= sp; argp++, num++)
+    {
+        switch(argp->type)
+        {
+        default:
+            sqlite3_finalize(stmt);
+            errorf("Bad argument %d to sl_exec(): type %s\n",
+                num+1, typename(argp->type));
+            break; /* NOTREACHED */
+
+        case T_FLOAT:
+            sqlite3_bind_double(stmt, num, READ_DOUBLE(argp));
+            break;
+
+        case T_NUMBER:
+            sqlite3_bind_int(stmt, num, argp->u.number);
+            break;
+    
+        case T_STRING:
+            sqlite3_bind_text(stmt, num, get_txt(argp->u.str),
+                mstrsize(argp->u.str), SQLITE_STATIC);
+            break;
+        }
+    }
+    
+    rows = 0;
+    cols = sqlite3_column_count(stmt);
+
+    rec_data = xalloc(sizeof(*rec_data));
+    if(!rec_data)
+    {
+        sqlite3_finalize(stmt);
+        errorf("(sl_exec) Out of memory: (%lu bytes) for cleanup structure\n",
+            (unsigned long) sizeof(*rec_data));
+    }
+    rec_data->rows = NULL;
+    rec_data->stmt = stmt;
+    
+    push_error_handler(sl_exec_cleanup, &(rec_data->head));
+    sp = inter_sp;
+    
+    while((err = sqlite3_step(stmt)) == SQLITE_ROW)
+    {
+        int col;
+        sqlite_rows_t *this_row;
+
+        rows++;
+        this_row = pxalloc(sizeof(*this_row));
+        if(!this_row)
+            errorf("(sl_exec) Out of memory: (%lu bytes)\n",
+                (unsigned long) sizeof(*this_row));
+
+        this_row->last = rec_data->rows;
+        rec_data->rows = this_row;
+        this_row->row = NULL; /* Because allocate_array may throw an error. */
+
+        this_row->row = allocate_array(cols);
+        if(!this_row->row)
+            errorf("(sl_exec) Out of memory: row vector\n");
+    
+        for(col = 0; col < cols; col++)
+        {
+            STORE_DOUBLE_USED;
+            svalue_t * entry;
+
+            entry = this_row->row->item + col;
+
+            switch(sqlite3_column_type(stmt, col))
+            {
+            default:
+                errorf("sl_exec: Unknown type %d.\n",
+                    sqlite3_column_type(stmt, col));
+                break;
+
+            case SQLITE_BLOB:
+                errorf("sl_exec: Blob columns are not supported.\n");
+                break;
+
+            case SQLITE_INTEGER:
+                put_number(entry, sqlite3_column_int(stmt, col));
+                break;
+
+           case SQLITE_FLOAT:
+                entry->type = T_FLOAT;
+                STORE_DOUBLE(entry, sqlite3_column_double(stmt, col));
+                break;
+
+            case SQLITE_TEXT:
+                put_c_n_string(entry,
+                    sqlite3_column_text(stmt, col),
+                    sqlite3_column_bytes(stmt, col));
+                break;
+
+            case SQLITE_NULL:
+                /* All elements from this_row->row are initialized to 0. */
+                break;
+            }
+        }
+    }
+
+    sqlite3_finalize(stmt);
+    rec_data->stmt = NULL;
+    
+    switch(err)
+    {
+    default:
+        errorf("sl_exec: Unknown return code from sqlite3_step: %d.\n", err);
+        break;
+
+    case SQLITE_BUSY:
+        errorf("sl_exec: Database is locked.\n");
+        break;
+
+    case SQLITE_ERROR:
+        errorf("sl_exec: %s\n", sqlite3_errmsg(db->db));
+        break;
+
+    case SQLITE_MISUSE:
+        errorf("sl_exec: sqlite3_step was called inappropriately.\n");
+        break;
+
+    case SQLITE_DONE:
+        break;
+    }
+
+    if(rows)
+    {
+        sqlite_rows_t *this_row;
+
+        result = allocate_array(rows);
+        if(!result)
+            errorf("(sl_exec) Out of memory: result vector\n");
+
+        this_row = rec_data->rows;
+        while(rows--)
+        {
+            put_array(result->item + rows, this_row->row);
+            this_row->row = NULL;
+            this_row = this_row->last;
+        }
+    }
+    else
+        result = NULL;
+
+    // Pop arguments and our error handler.
+    // Our error handler gets called and cleans the row stuff.
+    sp = pop_n_elems(num_arg + 1, sp) + 1; 
+    	
+    if(rows)
+        put_array(sp,result);
+    else
+        put_number(sp, 0);
+
+    return sp;
+}
+
+int
+sl_close (object_t *ob)
+{
+    sqlite_dbs_t *db = find_db(ob);
+    if (!db) return 0;
+   
+    sqlite3_close(db->db);
+    ob->open_sqlite_db=0;
+    remove_db(db);
+    return 1;
+}
+
+svalue_t *
+f_sl_insert_id (svalue_t * sp)
+{
+    sqlite_dbs_t *db = find_db(current_object);
+    int id;
+   
+    if (!db)
+        errorf("The current object doesn't have a database open.\n");
+ 
+    id=sqlite3_last_insert_rowid(db->db);
+    sp++;
+    put_number(sp,id);
+    return sp;
+}
+
+svalue_t * 
+f_sl_close (svalue_t * sp) 
+{
+    if (!sl_close(current_object)) 
+        errorf("The current object doesn't have a database open.\n");
+    return sp;
+}
+
+#endif /* USE_SQLITE3 */
diff -Naur 3.3/src/pkg-sqlite3.h 3.3sqlite/src/pkg-sqlite3.h
--- 3.3/src/pkg-sqlite3.h	1970-01-01 01:00:00.000000000 +0100
+++ 3.3sqlite/src/pkg-sqlite3.h	2005-12-06 00:07:18.000000000 +0100
@@ -0,0 +1,5 @@
+#ifdef USE_SQLITE3
+
+int sl_close (object_t *ob);
+
+#endif /* USE_SQLITE3 */
diff -Naur 3.3/src/simulate.c 3.3sqlite/src/simulate.c
--- 3.3/src/simulate.c	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/simulate.c	2005-12-06 00:27:40.000000000 +0100
@@ -53,6 +53,9 @@
 #include "mstrings.h"
 #include "object.h"
 #include "otable.h"
+#ifdef USE_SQLITE3
+#include "pkg-sqlite3.h"
+#endif
 #ifdef USE_TLS
 #include "pkg-tls.h"
 #endif
@@ -2059,6 +2062,9 @@
     ob->load_name = new_tabled(name);  /* but here it is */
     ob->prog = prog;
     ob->ticks = ob->gigaticks = 0;
+#ifdef USE_SQLITE3
+    ob->open_sqlite_db=0;
+#endif
     ob->next_all = obj_list;
     ob->prev_all = NULL;
     if (obj_list)
@@ -2302,6 +2308,9 @@
     if (!current_object)
         fatal("clone_object() from no current_object !\n");
 #endif
+#ifdef USE_SQLITE3
+    new_ob->open_sqlite_db=0;
+#endif
     new_ob->next_all = obj_list;
     new_ob->prev_all = NULL;
     if (obj_list)
@@ -2544,6 +2553,10 @@
 #ifdef CHECK_OBJECT_REF
     xallocate(shadow, sizeof(*shadow), "destructed object shadow");
 #endif /* CHECK_OBJECT_REF */
+
+#ifdef USE_SQLITE3
+    if (ob->open_sqlite_db) sl_close(ob);
+#endif
     ob->time_reset = 0;
 
     /* We need the object in memory */
diff -Naur 3.3/src/slaballoc.c 3.3sqlite/src/slaballoc.c
--- 3.3/src/slaballoc.c	2005-06-22 14:52:18.000000000 +0200
+++ 3.3sqlite/src/slaballoc.c	2005-12-06 00:13:39.000000000 +0100
@@ -230,7 +230,7 @@
 
 #if defined(SBRK_OK)
 #  ifdef MALLOC_SBRK
-#      if !defined(USE_PTHREADS)
+#      if !defined(USE_PTHREADS) && (!defined(USE_SQLITE3) || !defined(SQLITE3_USES_PTHREADS))
 #          define REPLACE_MALLOC
 #      else
 #          undef SBRK_OK
diff -Naur 3.3/src/smalloc.c 3.3sqlite/src/smalloc.c
--- 3.3/src/smalloc.c	2005-11-08 08:31:45.000000000 +0100
+++ 3.3sqlite/src/smalloc.c	2005-12-06 00:13:18.000000000 +0100
@@ -243,7 +243,7 @@
 
 #if defined(SBRK_OK)
 #  ifdef MALLOC_SBRK
-#      if !defined(USE_PTHREADS)
+#      if !defined(USE_PTHREADS) && (!defined(USE_SQLITE3) || !defined(SQLITE3_USES_PTHREADS))
 #          define REPLACE_MALLOC
 #      else
 #          undef SBRK_OK
diff -Naur 3.3/src/string_spec 3.3sqlite/src/string_spec
--- 3.3/src/string_spec	2005-11-08 08:31:45.000000000 +0100
+++ 3.3sqlite/src/string_spec	2005-12-06 00:05:58.000000000 +0100
@@ -229,5 +229,8 @@
 SUCCESS         "success"
 
 #endif
+#ifdef USE_SQLITE3
+SQLITE_OPEN	"sl_open"
+#endif
 
 /***************************************************************************/
diff -Naur 3.3/src/xalloc.c 3.3sqlite/src/xalloc.c
--- 3.3/src/xalloc.c	2005-11-25 08:19:27.000000000 +0100
+++ 3.3sqlite/src/xalloc.c	2005-12-06 00:12:03.000000000 +0100
@@ -329,6 +329,15 @@
 #    warning ""
 #endif
 
+#if defined(USE_SQLITE3) && defined(SQLITE3_USES_PTHREADS) && !defined(MEM_THREADSAFE) && !defined(MEM_MAIN_THREADSAFE)
+#    warning ""
+#    warning "-----------------------------------"
+#    warning "SQLite3 uses PThreads, but the allocator"
+#    warning "is not threadsafe!"
+#    warning "-----------------------------------"
+#    warning ""
+#endif
+
 #if defined(MALLOC_ptmalloc) && defined(GC_SUPPORT) && defined(__FreeBSD__)
 #    warning ""
 #    warning "-----------------------------------"
