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);