diff --git a/.gitattributes b/.gitattributes
index d27c86aae2e715013bd04da4b99de0f317010ed2..67f73e7ccd9e9f9a024042d2b9a0c838df75c3de 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -67,6 +67,10 @@ testfont binary
 /src/modules/Odbc/odbc.c foreign_ident
 /src/modules/Odbc/odbc_result.c foreign_ident
 /src/modules/Odbc/precompiled_odbc.h foreign_ident
+/src/modules/Oracle/Makefile.in foreign_ident
+/src/modules/Oracle/acconfig.h foreign_ident
+/src/modules/Oracle/configure.in foreign_ident
+/src/modules/Oracle/oracle.c foreign_ident
 /src/modules/Pipe/pipe.c foreign_ident
 /src/modules/Regexp/acconfig.h foreign_ident
 /src/modules/Ssleay/ssleay.c foreign_ident
diff --git a/src/modules/Oracle/.cvsignore b/src/modules/Oracle/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..3a5fcc9b7b5e80cc57e0cb8f16c49204a7e0abb6
--- /dev/null
+++ b/src/modules/Oracle/.cvsignore
@@ -0,0 +1,10 @@
+.pure
+Makefile
+config.h.in
+config.log
+config.status
+configure
+dependencies
+linker_options
+stamp-h
+stamp-h.in
diff --git a/src/modules/Oracle/.gitignore b/src/modules/Oracle/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a5317fbd105b018042f2a89481eceaf676a128c1
--- /dev/null
+++ b/src/modules/Oracle/.gitignore
@@ -0,0 +1,10 @@
+/.pure
+/Makefile
+/config.h.in
+/config.log
+/config.status
+/configure
+/dependencies
+/linker_options
+/stamp-h
+/stamp-h.in
diff --git a/src/modules/Oracle/Makefile.in b/src/modules/Oracle/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..798a47b19b8335d3ff982cd8b6153a351cc6012c
--- /dev/null
+++ b/src/modules/Oracle/Makefile.in
@@ -0,0 +1,12 @@
+#
+# $Id: Makefile.in,v 1.1 1997/05/17 01:56:29 marcus Exp $
+#
+
+SRCDIR=@srcdir@
+VPATH=@srcdir@:@srcdir@/../..:../..
+MODULE_CPPFLAGS=@DEFS@ @CPPFLAGS@
+OBJS=oracle.o
+MODULE_LDFLAGS=@LDFLAGS@ @ORACLE_LIBS@
+
+@dynamic_module_makefile@
+@dependencies@
diff --git a/src/modules/Oracle/acconfig.h b/src/modules/Oracle/acconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5bb40bb47564cd41018f547f312663d35b7643c
--- /dev/null
+++ b/src/modules/Oracle/acconfig.h
@@ -0,0 +1,24 @@
+/*
+ * $Id: acconfig.h,v 1.1 1997/05/17 01:56:31 marcus Exp $
+ *
+ * Config-file for the Pike Oracle-module.
+ *
+ * Marcus Comstedt
+ */
+
+#ifndef PIKE_ORACLE_CONFIG_H
+#define PIKE_ORACLE_CONFIG_H
+
+@TOP@
+@BOTTOM@
+
+/* Define if you have Oracle */
+#undef HAVE_ORACLE
+
+/* Define to path of Oracle home directory */
+#undef ORACLE_HOME
+
+/* Define to sid of Oracle server */
+#undef ORACLE_SID
+
+#endif /* PIKE_ORACLE_CONFIG_H */
diff --git a/src/modules/Oracle/configure.in b/src/modules/Oracle/configure.in
new file mode 100755
index 0000000000000000000000000000000000000000..867d9fa262e17422164a71924cc45abe1b4a7f3d
--- /dev/null
+++ b/src/modules/Oracle/configure.in
@@ -0,0 +1,95 @@
+#
+# $Id: configure.in,v 1.1 1997/05/17 01:56:32 marcus Exp $
+#
+# Configure script for the oracle module
+#
+
+AC_INIT(oracle.c)
+AC_CONFIG_HEADER(config.h)
+
+sinclude(../module_configure.in)
+
+ORACLE_LIBS=""
+
+AC_ARG_WITH(oracle,  [  --without-oracle       no support for the Oracle databases],[],[with_oracle=yes])
+
+if test x$with_oracle = xyes; then
+
+  AC_MSG_CHECKING(for Oracle oratab)
+
+  oratab_locations="/var/opt/oracle/oratab /hemligt/ställe/där/filerna/ligger/under/AIX"
+
+  AC_CACHE_VAL(pike_cv_oracle_oratab_file, [
+
+    for pike_cv_oracle_oratab_file in $oratab_locations no; do
+      if test -f $pike_cv_oracle_oratab_file; then
+        break
+      else
+        :
+      fi
+    done
+
+  ])
+
+  AC_MSG_RESULT($pike_cv_oracle_oratab_file)
+
+  if test x$pike_cv_oracle_oratab_file = xno; then :; else
+
+    AC_MSG_CHECKING(for Oracle libraries)
+
+    echo no > conftest
+      
+    sed -e '/^#/d' < $pike_cv_oracle_oratab_file | while IFS=":" read sid dir bootstart; do
+      if test -d "$dir/." -a -f "$dir/lib/libclient.a"; then
+        AC_DEFINE_UNQUOTED(ORACLE_HOME, "${dir}")
+        AC_DEFINE_UNQUOTED(ORACLE_SID, "${sid}")
+	echo "$dir/lib" > conftest
+	break
+      else
+	:
+      fi
+    done
+
+    IFS="" read oracle_lib_dir < conftest
+
+    AC_MSG_RESULT($oracle_lib_dir)
+
+    AC_MSG_CHECKING(for Oracle includes)
+
+    echo no > conftest
+      
+    sed -e '/^#/d' < $pike_cv_oracle_oratab_file | while IFS=":" read sid dir bootstart; do
+      if test -d "$dir/." -a -f "$dir/rdbms/demo/ocidfn.h"; then
+	echo "$dir/rdbms/demo" > conftest
+	break
+      else
+	:
+      fi
+    done
+
+    IFS="" read oracle_include_dir < conftest
+
+    AC_MSG_RESULT($oracle_include_dir)
+
+    if test "x$oracle_lib_dir" = xno -o "x$oracle_include_dir" = xno; then :; else
+
+      CPPFLAGS="-I\"$oracle_include_dir\" ${CPPFLAGS}"
+
+      dnl ORACLE_LIBS="-L\"$oracle_lib_dir\" -lclient -lnlsrtl3 -lcommon -lsqlnet -lnlsrtl3 -lcore3 -lcommon -lnlsrtl3 -lgeneric -lcv6 -lnlsrtl3 -lncr -lcore3 -lsqlnet -lepc"
+
+      ORACLE_LIBS="-L\"$oracle_lib_dir\" -lclient -lsqlnet -lncr -lsqlnet -lclient -lcommon -lgeneric -lsqlnet -lncr -lsqlnet -lclient -lcommon -lgeneric -lepc -lnlsrtl3 -lc3v6 -lcore3 -lnlsrtl3 -lcore3 -lnlsrtl3 -lsocket -lnsl -lm -ldl -laio -lm -lcore3"
+
+      AC_DEFINE(HAVE_ORACLE)
+
+    fi
+
+  fi
+
+else
+  :
+fi
+
+AC_SUBST(ORACLE_LIBS)
+
+AC_OUTPUT(Makefile,echo FOO >stamp-h )
+
diff --git a/src/modules/Oracle/oracle.c b/src/modules/Oracle/oracle.c
new file mode 100644
index 0000000000000000000000000000000000000000..b5c345a8b7191915f6b9c55eedf8369990a1fc6b
--- /dev/null
+++ b/src/modules/Oracle/oracle.c
@@ -0,0 +1,544 @@
+#include <global.h>
+#include <svalue.h>
+#include <object.h>
+#include <array.h>
+#include <stralloc.h>
+#include <interpret.h>
+#include <pike_types.h>
+#include <threads.h>
+#include <module_support.h>
+#include <mapping.h>
+#include <builtin_functions.h>
+
+#ifdef HAVE_ORACLE
+
+#include <ocidfn.h>
+#include <ociapr.h>
+
+#endif
+
+#include "config.h"
+
+RCSID("$Id: oracle.c,v 1.1 1997/05/17 01:56:33 marcus Exp $");
+
+#ifdef HAVE_ORACLE
+
+#undef THREADS_ALLOW
+#define THREADS_ALLOW()
+#undef THREADS_DISALLOW
+#define THREADS_DISALLOW()
+
+struct program *oracle_program = NULL, *oracle_result_program = NULL;
+
+struct dbcurs {
+  struct dbcurs *next;
+  Cda_Def cda;
+};
+
+struct dbcon {
+  Lda_Def lda;
+  ub4 hda[128];
+  struct dbcurs *cdas, *share_cda;
+};
+
+struct dbresult {
+  struct object *parent;
+  struct dbcon *dbcon;
+  struct dbcurs *curs;
+  Cda_Def *cda;
+  INT32 cols;
+};
+
+
+static void error_handler(struct dbcon *dbcon, sword rc)
+{
+  static text msgbuf[512];
+  oerhms(&dbcon->lda, rc, msgbuf, sizeof(msgbuf));
+  error(msgbuf);
+}
+
+
+#define THIS ((struct dbresult *)(fp->current_storage))
+
+static void init_dbresult_struct(struct object *o)
+{
+  memset(THIS, 0, sizeof(*THIS));
+}
+
+static void exit_dbresult_struct(struct object *o)
+{
+  struct dbresult *r = THIS;
+
+  if(r->curs) {
+    ocan(&r->curs->cda);
+    r->curs->next = r->dbcon->cdas;
+    r->dbcon->cdas = r->curs;
+  }
+
+  if(r->parent)
+    free_object(r->parent);
+}
+
+static void f_result_create(INT32 args)
+{
+  struct object *p;
+  struct dbcon *dbcon;
+  struct dbcurs *curs;
+  struct dbresult *r = THIS;
+  INT32 i;
+
+  get_all_args("Oracle.oracle_result->create", args, "%o", &p);
+  
+  if(!(dbcon = (struct dbcon *)get_storage(p, oracle_program)) ||
+     !(curs = dbcon->share_cda))
+    error("Bad argument 1 to Oracle.oracle_result->create()\n");
+
+  r->curs = curs;
+  dbcon->share_cda = NULL;
+
+  r->parent = p;
+  r->dbcon = dbcon;
+  r->cda = &curs->cda;
+  p->refs++;
+
+  r->cols = 0;
+}
+
+static void f_num_fields(INT32 args)
+{
+  struct dbresult *r = THIS;
+
+  if(THIS->cols == 0) {
+    sword rc;
+    INT32 i;
+    sb4 siz;
+
+    THREADS_ALLOW();
+
+    for(i=11; ; i+=10)
+      if((rc = odescr(r->cda, i, &siz, NULL, NULL, NULL, NULL,
+		      NULL, NULL, NULL)))
+	break;
+
+    if(r->cda->rc == 1007)
+      for(i-=10; ; i++)
+	if((rc = odescr(r->cda, i, &siz, NULL, NULL, NULL, NULL,
+			NULL, NULL, NULL)))
+	  break;
+
+    THREADS_DISALLOW();    
+
+    if(r->cda->rc != 1007)
+      error_handler(r->dbcon, r->cda->rc);
+
+    THIS->cols = i-1;
+  }
+  pop_n_elems(args);
+  push_int(THIS->cols);
+}
+
+static void f_fetch_fields(INT32 args)
+{
+  struct dbresult *r = THIS;
+  INT32 i, nambufsz=64;
+  sword rc;
+  text *nambuf=xalloc(nambufsz+1);
+
+  pop_n_elems(args);
+
+  for(i=0; i<r->cols || r->cols == 0; i++) {
+
+    sb4 siz, cbufl, dispsz;
+    sb2 typ, scale;
+
+    for(;;) {
+
+      cbufl = nambufsz;
+      
+      THREADS_ALLOW();
+      
+      rc = odescr(r->cda, i+1, &siz, &typ, nambuf, &cbufl, &dispsz,
+		  NULL, &scale, NULL);
+      
+      THREADS_DISALLOW();
+
+      if(rc || cbufl < nambufsz) break;
+
+      free(nambuf);
+      nambuf = xalloc((nambufsz <<= 1)+1);
+
+    }
+
+    if(rc) {
+      if(r->cda->rc == 1007)
+	break;
+      free(nambuf);
+      error_handler(r->dbcon, r->cda->rc);
+    }
+
+    push_text("name");
+    push_string(make_shared_binary_string(nambuf, cbufl));
+    push_text("type");
+    switch(typ) {
+    case 1:
+      push_text("varchar2");
+      break;
+    case 2:
+      push_text("number");
+      break;
+    case 8:
+      push_text("long");
+      break;
+    case 11:
+      push_text("rowid");
+      break;
+    case 12:
+      push_text("date");
+      break;
+    case 23:
+      push_text("raw");
+      break;
+    case 24:
+      push_text("long raw");
+      break;
+    case 96:
+      push_text("char");
+      break;
+    case 105:
+      push_text("mslabel");
+      break;
+    default:
+      push_int(0);
+      break;
+    }
+    push_text("length");
+    push_int(dispsz);
+    push_text("decimals");
+    push_int(scale);
+    f_aggregate_mapping(8);
+  }
+
+  free(nambuf);
+
+  if(r->cols == 0)
+    r->cols = i;
+
+  f_aggregate(r->cols);
+}
+
+static void f_fetch_row(INT32 args)
+{
+  struct fetchslot {
+    struct fetchslot *next;
+    INT32 siz;
+    ub2 rsiz, rcode;
+    sb2 indp;
+    char data[1];
+  } *s, *s2, *slots = NULL;
+  struct dbresult *r = THIS;
+  sword rc;
+  INT32 i;
+
+  pop_n_elems(args);
+
+  for(i=0; i<r->cols || r->cols == 0; i++) {
+    sb4 siz, dsiz;
+
+    THREADS_ALLOW();
+
+    rc = odescr(r->cda, i+1, &siz, NULL, NULL, NULL, &dsiz,
+		NULL, NULL, NULL);
+
+    THREADS_DISALLOW();    
+
+    if(rc) {
+      if(r->cda->rc == 1007)
+	break;
+      while((s=slots)) {
+	slots=s->next;
+	free(s);
+      }
+      error_handler(r->dbcon, r->cda->rc);
+    }
+    
+    s = (struct fetchslot *)xalloc(sizeof(struct fetchslot)+dsiz+2);
+
+    s->next = slots;
+    s->siz = dsiz+2;
+    slots = s;
+
+    THREADS_ALLOW();
+
+    s->rcode = 0;
+    s->indp = -1;
+
+    rc = odefin(r->cda, i+1, s->data, s->siz, SQLT_STR, -1, &s->indp, NULL,
+		-1, -1, &s->rsiz, &s->rcode);		
+
+    THREADS_DISALLOW();
+
+    if(rc) {
+      while((s=slots)) {
+	slots=s->next;
+	free(s);
+      }
+      error_handler(r->dbcon, r->cda->rc);
+    }
+  }
+
+  if(r->cols == 0)
+    r->cols = i;
+
+  /* Do link reversal */
+  for(s=NULL; slots; slots=s2) {
+    s2 = slots->next;
+    slots->next = s;
+    s = slots;
+  }
+  slots = s;
+
+  THREADS_ALLOW();
+
+  rc = ofetch(r->cda);
+
+  THREADS_DISALLOW();
+
+  if(rc) {
+    while((s=slots)) {
+      slots=s->next;
+      free(s);
+    }
+    if(r->cda->rc == 1403) {
+      push_int(0);
+      return;
+    } else error_handler(r->dbcon, r->cda->rc);
+  }
+
+  for(s=slots, i=0; i<r->cols; i++) {
+    if(s->indp == -1)
+      push_int(0);
+    else if(s->rcode /* == 1406 */)
+      push_int(0);
+    else
+      push_string(make_shared_binary_string(s->data, s->rsiz));
+    s2=s->next;
+    free(s);
+    s=s2;
+  }
+
+  f_aggregate(r->cols);
+}
+
+#undef THIS
+#define THIS ((struct dbcon *)(fp->current_storage))
+
+static void init_dbcon_struct(struct object *o)
+{
+  memset(THIS, 0, sizeof(*THIS));
+}
+
+static void exit_dbcon_struct(struct object *o)
+{
+  struct dbcon *dbcon = THIS;
+  struct dbcurs *curs;
+  ologof(&dbcon->lda);
+  while((curs = dbcon->cdas) != NULL) {
+    dbcon->cdas = curs->next;
+    free(curs);
+  }
+}
+
+static struct dbcurs *make_cda(struct dbcon *dbcon)
+{
+  sword rc;
+  struct dbcurs *curs=(struct dbcurs *)xalloc(sizeof(struct dbcurs));
+
+  memset(curs, 0, sizeof(*curs));
+
+  THREADS_ALLOW();
+
+  rc=oopen(&curs->cda, &dbcon->lda, NULL, -1, -1, NULL, -1);
+
+  THREADS_DISALLOW();
+
+  if(rc) {
+    rc = curs->cda.rc;
+    free(curs);
+    error_handler(dbcon, rc);
+  } else {
+    curs->next = dbcon->cdas;
+    dbcon->cdas = curs;
+  }
+  return curs;
+}
+
+static void f_create(INT32 args)
+{
+  struct dbcon *dbcon = THIS;
+  struct pike_string *uid, *passwd, *host, *database;
+  sword rc;
+
+  check_all_args("Oracle.oracle->create", args,
+		 BIT_STRING|BIT_INT, BIT_STRING|BIT_INT, BIT_STRING,
+		 BIT_STRING|BIT_VOID|BIT_INT, 0);
+
+  host = (sp[-args].type == T_STRING? sp[-args].u.string : NULL);
+  database = (sp[1-args].type == T_STRING? sp[1-args].u.string : NULL);
+  uid = (sp[2-args].type == T_STRING? sp[2-args].u.string : NULL);
+  if(args >= 4)
+    passwd = (sp[3-args].type == T_STRING? sp[3-args].u.string : NULL);
+  else
+    passwd = NULL;
+
+  THREADS_ALLOW();
+
+  rc = olog(&dbcon->lda, (ub1*)dbcon->hda, uid->str, uid->len,
+	    (passwd? passwd->str:NULL), (passwd? passwd->len:-1),
+	    (host? host->str:NULL), (host? host->len:-1),
+	    OCI_LM_DEF);
+
+  THREADS_DISALLOW();
+
+  if(rc)
+    error_handler(dbcon, dbcon->lda.rc);
+
+  make_cda(dbcon);
+
+  pop_n_elems(args);
+  return;
+}
+
+static void f_big_query(INT32 args)
+{
+  struct pike_string *query;
+  struct dbcurs *curs;
+  sword rc;
+  INT32 cols=0;
+
+  get_all_args("Oracle.oracle->big_query", args, "%S", &query);
+
+  if(!(curs = THIS->cdas))
+    curs = make_cda(THIS);
+
+  THIS->cdas = curs->next;
+
+  THREADS_ALLOW();
+
+  ocan(&curs->cda);
+
+  rc = oparse(&curs->cda, query->str, query->len, 1, 2);
+ 
+  THREADS_DISALLOW();
+   
+  if(rc) {
+    curs->next = THIS->cdas;
+    THIS->cdas = curs;
+    error_handler(THIS, curs->cda.rc);
+  }
+
+  THREADS_ALLOW();
+
+  rc = oexec(&curs->cda);
+
+  THREADS_DISALLOW();
+
+  if(rc) {
+    rc = curs->cda.rc;
+    ocan(&curs->cda);
+    curs->next = THIS->cdas;
+    THIS->cdas = curs;
+    error_handler(THIS, rc);
+  }
+
+  pop_n_elems(args);
+
+  push_object(this_object());
+
+  for(;;) {
+    text cbuf[32];
+    sb4 siz, cbufl=sizeof(cbuf), dispsz;
+    sb2 typ, prec, scale, nullok;
+
+    THREADS_ALLOW();
+
+    rc = odescr(&curs->cda, cols+1, &siz, &typ, cbuf, &cbufl, &dispsz,
+		&prec, &scale, &nullok);
+
+    THREADS_DISALLOW();
+
+    if(rc) {
+      if((rc = curs->cda.rc) == 1007)
+	break;
+      ocan(&curs->cda);
+      curs->next = THIS->cdas;
+      THIS->cdas = curs;
+      error_handler(THIS, rc);
+    }
+    push_string(make_shared_binary_string(cbuf, cbufl));
+    push_int(typ);
+    cols++;
+  }
+
+  curs->next = THIS->cdas;
+  THIS->cdas = curs;
+
+  if(!cols) {
+    ocan(&curs->cda);
+    pop_n_elems(1);
+    push_int(0);
+    return;
+  }
+
+  f_aggregate(cols*2);
+
+  THIS->share_cda = curs;
+
+  push_object(clone_object(oracle_result_program, 2));
+
+  THIS->cdas = curs->next;
+}
+
+#endif
+
+void pike_module_init(void)
+{
+#ifdef HAVE_ORACLE
+  /*  opinit(OCI_EV_TSF); */
+
+  start_new_program();
+  add_storage(sizeof(struct dbcon));
+
+  add_function("create", f_create, "function(string|void, string|void, string|void, string|void:void)", ID_PUBLIC);
+  add_function("big_query", f_big_query, "function(string:object)", ID_PUBLIC);
+
+  set_init_callback(init_dbcon_struct);
+  set_exit_callback(exit_dbcon_struct);
+
+  oracle_program = end_program();
+  add_program_constant("oracle", oracle_program, 0);
+
+  start_new_program();
+  add_storage(sizeof(struct dbresult));
+
+  add_function("create", f_result_create, "function(object, array(string|int):void)", ID_PUBLIC);
+  add_function("num_fields", f_num_fields, "function(:int)", ID_PUBLIC);
+  add_function("fetch_fields", f_fetch_fields, "function(:array(mapping(string:mixed)))", ID_PUBLIC);
+  add_function("fetch_row", f_fetch_row, "function(:int|array(string|int))", ID_PUBLIC);
+
+  set_init_callback(init_dbresult_struct);
+  set_exit_callback(exit_dbresult_struct);
+
+  oracle_result_program = end_program();
+#endif
+}
+
+void pike_module_exit(void)
+{
+#ifdef HAVE_ORACLE
+  if (oracle_result_program) {
+    free_program(oracle_result_program);
+    oracle_program = NULL;
+  }
+#endif
+}
+