diff --git a/src/ChangeLog b/src/ChangeLog
index 4c11cfa588b33a9e168c061fc1a9d9ac28d19f75..80e3989f0a961619e1e5449f2d295e6e83eea562 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+Tue Oct  8 06:19:19 1996  Fredrik Hubinette  <hubbe@cuckoo.infovav.se>
+
+	* New efun: load module
+	* bug in copy_mapping fixed
+
 Sat Oct  5 02:53:14 1996  Fredrik Hubinette  <hubbe@teleute.infovav.se>
 
 	* /precompiled/fifo added (with #include <fifo.h>)
diff --git a/src/Makefile.src b/src/Makefile.src
index 374e6ca126e31e5f3811007d13cbc4041de796ec..41491904a8d25283714cc79fa82ffe7a52b85b02 100644
--- a/src/Makefile.src
+++ b/src/Makefile.src
@@ -75,6 +75,7 @@ OBJ= \
  callback.o \
  docode.o \
  dynamic_buffer.o \
+ dynamic_load.o \
  error.o \
  fd_control.o \
  fsort.o \
diff --git a/src/configure.in b/src/configure.in
index 611db64d847f96ec0d9ab882abc7527f27de6121..73c7e4768c2e2e36b80fef295c6774d2cb7199fa 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -245,7 +245,7 @@ AC_HEADER_TIME
 AC_HEADER_STDC
 AC_CHECK_HEADERS(sys/rusage.h time.h sys/time.h sys/types.h unistd.h stdlib.h \
 memory.h values.h string.h fcntl.h sys/filio.h sys/sockio.h crypt.h locale.h \
-sys/resource.h sys/select.h sys/mman.h setjmp.h limits.h pthread.h)
+sys/resource.h sys/select.h sys/mman.h setjmp.h limits.h pthread.h dlfcn.h)
 
 AC_SIZEOF_TYPE(char *)
 AC_SIZEOF_TYPE(long)
@@ -265,6 +265,7 @@ dnl AC_CHECK_LIB(PW, alloca)
 dnl AC_CHECK_LIB(crypt, crypt)
 
 AC_CHECK_LIB(m, floor)
+AC_CHECK_LIB(dl, dlopen)
 
 if test "${ac_cv_lib_m}" = "no" -a "${pike_cv_sys_os}" = "Linux"; then
   AC_MSG_WARN(I will compensate for this by adding -lc -lm)
@@ -367,6 +368,8 @@ AC_CHECK_FUNCS(
  wait4 \
  waitpid \
  munmap \
+ dlopen \
+ dlsym \
 )
 
 AC_STRUCT_TM
diff --git a/src/dynamic_load.c b/src/dynamic_load.c
new file mode 100644
index 0000000000000000000000000000000000000000..0992ea00ef39758f102439d9703c2f80a1478b91
--- /dev/null
+++ b/src/dynamic_load.c
@@ -0,0 +1,125 @@
+#include "global.h"
+
+#if !defined(HAVE_DLFCN_H) || !defined(HAVE_DLSYM) || !defined(HAVE_DLOPEN)
+#undef HAVE_DLOPEN
+#endif
+
+#ifdef HAVE_DLOPEN
+#include "interpret.h"
+#include "constants.h"
+#include "error.h"
+#include "module.h"
+#include "stralloc.h"
+#include "macros.h"
+#include <dlfcn.h>
+
+struct module_list
+{
+  struct module_list * next;
+  void *module;
+  struct module mod;
+};
+
+struct module_list *dynamic_module_list = 0;
+
+void f_load_module(INT32 args)
+{
+  void *module;
+  struct module_list *new_module;
+
+  if(sp[-args].type != T_STRING)
+    error("Bad argument 1 to load_module()\n");
+  module=dlopen(sp[-args].u.string->str, RTLD_NOW);
+  pop_stack();
+
+  if(module)
+  {
+    struct module *tmp;
+    void *init, *init2, *exit;
+    init=dlsym(module, "init_module_efuns");
+    init2=dlsym(module, "init_module_programs");
+    exit=dlsym(module, "exit_module");
+
+    if(!init || !init2 || !exit)
+    {
+      char *foo,  buf1[1024], buf2[1024];
+      foo=STRRCHR(sp[-args].u.string->str,'/');
+      if(!foo) foo=sp[-args].u.string->str;
+      foo++;
+      if(strlen(foo) < 1000)
+      {
+	strcpy(buf1, foo);
+	foo=buf1;
+      
+	while((*foo <= 'a' && *foo >= 'z' ) || (*foo <= 'A' && *foo >= 'Z' ))
+	  foo++;
+
+	*foo=0;
+      
+	strcpy(buf2,"init_");
+	strcat(buf2,buf1);
+	strcat(buf2,"_efuns");
+	init=dlsym(module, buf2);
+
+	strcpy(buf2,"init_");
+	strcat(buf2,buf1);
+	strcat(buf2,"_programs");
+	init2=dlsym(module, buf2);
+
+	strcpy(buf2,"exit_");
+	strcat(buf2,buf1);
+	exit=dlsym(module, buf2);
+      }
+    }
+
+    if(!init || !init2 || !exit)
+      error("Failed to initialize module.\n");
+
+    new_module=ALLOC_STRUCT(module_list);
+    new_module->next=dynamic_module_list;
+    dynamic_module_list=new_module;
+    new_module->module=module;
+    new_module->mod.init_efuns=init;
+    new_module->mod.init_programs=init2;
+    new_module->mod.exit=exit;
+    new_module->mod.refs=0;
+
+    tmp=current_module;
+    current_module=& new_module->mod;
+
+    (*(fun)init)();
+    (*(fun)init2)();
+
+    current_module=tmp;
+
+    push_int(1);
+  } else {
+    push_int(0);
+  }
+}
+
+
+#endif
+
+void init_dynamic_load()
+{
+#ifdef HAVE_DLOPEN
+  add_efun("load_module",f_load_module,"function(string:int)",OPT_SIDE_EFFECT);
+#endif
+}
+
+void exit_dynamic_load()
+{
+#ifdef HAVE_DLOPEN
+  while(dynamic_module_list)
+  {
+    struct module_list *tmp=dynamic_module_list;
+    dynamic_module_list=tmp->next;
+    (*tmp->mod.exit)();
+    dlclose(tmp->module);
+    free((char *)tmp);
+  }
+#endif
+}
+
+
diff --git a/src/dynamic_load.h b/src/dynamic_load.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb9ef46ea3d292de5421d861e600ab17a6592375
--- /dev/null
+++ b/src/dynamic_load.h
@@ -0,0 +1,11 @@
+#ifndef DYNAMIC_LOAD_H
+#define DYNAMIC_LOAD_H
+
+/* Prototypes begin here */
+struct module_list;
+void f_load_module(INT32 args);
+void init_dynamic_load();
+void exit_dynamic_load();
+/* Prototypes end here */
+
+#endif
diff --git a/src/machine.h.in b/src/machine.h.in
index d05f671ebfbe6030918cbf1d529084f58105d50c..26f1c88c89ca10ff79d5bed3780f67566c1ed6e5 100644
--- a/src/machine.h.in
+++ b/src/machine.h.in
@@ -335,4 +335,13 @@
 #undef _REENTRANT
 #undef _THREAD_SAFE
 
+/* Define this if you have dlopen() */
+#define HAVE_DLOPEN
+
+/* Define this if you have dlsym() */
+#define HAVE_DLSYM
+
+/* Define this if you have <dlfcn.h> */
+#define HAVE_DLFCN_H
+
 #endif /* MACHINE_H */
diff --git a/src/main.c b/src/main.c
index 99e2e9ff1e77a2f90554c539faa335e896302b5f..16e86ff9fe7d7e2097bc210d4c3e58ea2e4cd9aa 100644
--- a/src/main.c
+++ b/src/main.c
@@ -253,6 +253,7 @@ void init_main_efuns()
   init_builtin_efuns();
   init_signals();
   th_init();
+  init_dynamic_load();
 }
 
 void init_main_programs()
@@ -268,7 +269,7 @@ void exit_main()
   void cleanup_program();
 
   th_cleanup();
-
+  exit_dynamic_load();
   cleanup_objects();
   exit_signals();
   exit_lex();
diff --git a/src/stralloc.c b/src/stralloc.c
index 646a8897009b7018394d43739c93009a1952403e..ee04da58a755b9659c848b549a4a4bcf1259951c 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -102,13 +102,16 @@ static struct pike_string *internal_findstring(const char *s,int len,int h)
   return 0; /* not found */
 }
 
-struct pike_string *findstring(const char *foo)
+struct pike_string *binary_findstring(const char *foo, INT32 l)
 {
-  int l;
-  l=strlen(foo);
   return internal_findstring(foo, l, StrHash(foo,l));
 }
 
+struct pike_string *findstring(const char *foo)
+{
+  return binary_findstring(foo, strlen(foo));
+}
+
 /*
  * find a string that is already shared and move it to the head
  * of that list in the hastable
@@ -148,6 +151,7 @@ struct pike_string *begin_shared_string(int len)
 {
   struct pike_string *t;
   t=(struct pike_string *)xalloc(len + sizeof(struct pike_string));
+  t->str[len]=0;
   t->len=len;
   return t;
 }
@@ -166,7 +170,6 @@ struct pike_string *end_shared_string(struct pike_string *s)
     free((char *)s);
     s=s2;
   }else{
-    s->str[len]=0;
     s->refs = 0;
     s->next = base_table[h];
     base_table[h] = s;
diff --git a/src/stralloc.h b/src/stralloc.h
index f6e63b2cb2e6eab37df953f2ebcaf46f0de5905c..c9979ccf8766f1fb4288af925fc03fad8894bf61 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -34,6 +34,7 @@ struct pike_string *debug_findstring(const struct pike_string *foo);
 /* Prototypes begin here */
 void check_string(struct pike_string *s);
 void verify_shared_strings_tables();
+struct pike_string *binary_findstring(const char *foo, INT32 len);
 struct pike_string *findstring(const char *foo);
 struct pike_string *debug_findstring(const struct pike_string *foo);
 struct pike_string *begin_shared_string(int len);