From ca74dd50e111af589f62face92f7ee50c7655f32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Tue, 8 Oct 1996 06:24:50 +0200
Subject: [PATCH] dynamic module loading implemented

Rev: src/ChangeLog:1.8
Rev: src/Makefile.src:1.10
Rev: src/configure.in:1.7
Rev: src/dynamic_load.c:1.1
Rev: src/dynamic_load.h:1.1
Rev: src/machine.h.in:1.6
Rev: src/main.c:1.7
Rev: src/stralloc.c:1.2
Rev: src/stralloc.h:1.2
---
 src/ChangeLog      |   5 ++
 src/Makefile.src   |   1 +
 src/configure.in   |   5 +-
 src/dynamic_load.c | 125 +++++++++++++++++++++++++++++++++++++++++++++
 src/dynamic_load.h |  11 ++++
 src/machine.h.in   |   9 ++++
 src/main.c         |   3 +-
 src/stralloc.c     |  11 ++--
 src/stralloc.h     |   1 +
 9 files changed, 165 insertions(+), 6 deletions(-)
 create mode 100644 src/dynamic_load.c
 create mode 100644 src/dynamic_load.h

diff --git a/src/ChangeLog b/src/ChangeLog
index 4c11cfa588..80e3989f0a 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 374e6ca126..41491904a8 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 611db64d84..73c7e4768c 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 0000000000..0992ea00ef
--- /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 0000000000..fb9ef46ea3
--- /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 d05f671ebf..26f1c88c89 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 99e2e9ff1e..16e86ff9fe 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 646a889700..ee04da58a7 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 f6e63b2cb2..c9979ccf87 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);
-- 
GitLab