e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifndef TESTING # include "global.h" # include "interpret.h" # include "constants.h" # include "error.h" # include "module.h" # include "stralloc.h" # include "pike_macros.h"
24ddc71998-03-28Henrik Grubbström (Grubba) 
79f71c1998-07-09Francesco Chemolli RCSID("$Id: dynamic_load.c,v 1.29 1998/07/09 12:45:35 grubba Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
79f71c1998-07-09Francesco Chemolli #endif /* !TESTING */ #ifdef HAVE_ERRNO_H #include <errno.h> #endif /* HAVE_ERRNO_H */ #ifdef HAVE_STRING_H #include <string.h> #endif /* HAVE_STRING_H */
ca74dd1996-10-08Fredrik Hübinette (Hubbe) 
9649491998-02-27Fredrik Hübinette (Hubbe) #if !defined(HAVE_DLOPEN) #if defined(HAVE_DLD_LINK) && defined(HAVE_DLD_GET_FUNC)
7860031997-01-22Bernhard Fastenrath #define USE_DLD
9649491998-02-27Fredrik Hübinette (Hubbe) #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #else
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_SHL_LOAD) && defined(HAVE_DL_H) #define USE_HPUX_DL #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #else
9649491998-02-27Fredrik Hübinette (Hubbe) #if defined(HAVE_LOADLIBRARY) && defined(HAVE_FREELIBRARY) && \ defined(HAVE_GETPROCADDRESS) && defined(HAVE_WINBASE_H) #define USE_LOADLIBRARY #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #endif #endif
79f71c1998-07-09Francesco Chemolli #endif
9649491998-02-27Fredrik Hübinette (Hubbe) #else #define HAVE_SOME_DLOPEN
7860031997-01-22Bernhard Fastenrath #endif
9649491998-02-27Fredrik Hübinette (Hubbe)  #ifdef HAVE_SOME_DLOPEN
2631a61996-10-09Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) typedef void (*modfun)(void);
9649491998-02-27Fredrik Hübinette (Hubbe) #ifdef USE_LOADLIBRARY #include <windows.h> static TCHAR *convert_string(char *str, int len) { int e; TCHAR *ret=(TCHAR *)xalloc((len+1) * sizeof(TCHAR)); for(e=0;e<len;e++) ret[e]=EXTRACT_UCHAR(str+e); ret[e]=0; return ret; } static void *dlopen(char *foo, int how) { TCHAR *tmp; HINSTANCE ret; tmp=convert_string(foo, strlen(foo)); ret=LoadLibrary(tmp); free((char *)tmp); return (void *)ret; } static char * dlerror(void) { static char buffer[200]; sprintf(buffer,"LoadLibrary failed with error: %d",GetLastError()); return buffer; } static void *dlsym(void *module, char * function) { return (void *)GetProcAddress((HMODULE)module, function); } static void dlclose(void *module) { FreeLibrary((HMODULE)module); } #define dlinit()
79f71c1998-07-09Francesco Chemolli #endif /* USE_LOADLIBRARY */
9649491998-02-27Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifdef USE_DLD #include <dld.h>
79f71c1998-07-09Francesco Chemolli static void *dlopen(char *module_name, int how)
e1195f1997-03-23Fredrik Hübinette (Hubbe) { dld_create_reference("pike_module_init"); if(dld_link(module_name)) { return (void *)strdup(module_name); }else{ return 0; } } static char *dlerror(void) { return dld_strerror(dld_errno); } static void *dlsym(void *module, char *function) { return dld_get_func(function); } static void *dlclose(void *module) { if(!module) return; dld_unlink_by_file((char *)module); free(module); } static void dlinit(void) { extern char ** ARGV; if(dld_init(dld_find_executable(ARGV[0]))) { fprintf(stderr,"Failed to init dld\n"); exit(1); } }
79f71c1998-07-09Francesco Chemolli #endif /* USE_DLD */ #ifdef USE_HPUX_DL #include <dl.h> #if defined(TESTING) && defined(BIND_VERBOSE) #define RTLD_NOW BIND_IMMEDIATE | BIND_VERBOSE #else #define RTLD_NOW BIND_IMMEDIATE #endif /* TESTING && BIND_VERBOSE */ extern int errno; static void *dlopen(char *libname, int how) { shl_t lib; lib = shl_load(libname, how, 0L); return (void *)lib; }
e1195f1997-03-23Fredrik Hübinette (Hubbe) 
79f71c1998-07-09Francesco Chemolli static char *dlerror(void) { #ifdef HAVE_STRERROR return strerror(errno); #else return ""; /* I hope it's better than null..*/
9649491998-02-27Fredrik Hübinette (Hubbe) #endif
79f71c1998-07-09Francesco Chemolli } static void *dlsym(void *module, char *function) { void *func; int result; shl_t mod = (shl_t)module; result = shl_findsym(&mod, function, TYPE_UNDEFINED, &func); if (result == -1) return NULL; return func; } static void dlclose(void *module) { shl_unload((shl_t)module); } #define dlinit() #endif /* USE_HPUX_DL */
9649491998-02-27Fredrik Hübinette (Hubbe)  #ifndef EMULATE_DLOPEN
2631a61996-10-09Fredrik Hübinette (Hubbe) #ifdef HAVE_DLFCN_H
ca74dd1996-10-08Fredrik Hübinette (Hubbe) #include <dlfcn.h>
2631a61996-10-09Fredrik Hübinette (Hubbe) #endif
ca74dd1996-10-08Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) #define dlinit()
79f71c1998-07-09Francesco Chemolli #endif /* !EMULATE_DLOPEN */
7860031997-01-22Bernhard Fastenrath 
e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifndef RTLD_NOW #define RTLD_NOW 0 #endif
79f71c1998-07-09Francesco Chemolli #endif
de16081997-06-03Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe)  #ifndef TESTING
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
6cf83a1997-02-06Fredrik Hübinette (Hubbe) 
ca74dd1996-10-08Fredrik Hübinette (Hubbe) struct module_list { struct module_list * next;
368fe71997-01-26Fredrik Hübinette (Hubbe)  void *module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  modfun init, exit;
368fe71997-01-26Fredrik Hübinette (Hubbe) }; struct module_list *dynamic_module_list = 0; void f_load_module(INT32 args) {
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  void *module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  modfun init, exit;
368fe71997-01-26Fredrik Hübinette (Hubbe)  struct module_list *new_module; const char *module_name; if(sp[-args].type != T_STRING) error("Bad argument 1 to load_module()\n"); module_name = sp[-args].u.string->str; module=dlopen(module_name, RTLD_NOW);
ef78b01997-11-03Henrik Grubbström (Grubba) 
368fe71997-01-26Fredrik Hübinette (Hubbe)  if(!module) {
466a321997-09-07Henrik Grubbström (Grubba)  const char *err = dlerror();
e1195f1997-03-23Fredrik Hübinette (Hubbe)  if(!err) err = "Unknown reason";
14160c1998-05-15Henrik Grubbström (Grubba)  if (sp[-args].u.string->len < 1024) { error("load_module(\"%s\") failed: %s\n", sp[-args].u.string->str, err); } else { error("load_module() failed: %s\n", err); }
368fe71997-01-26Fredrik Hübinette (Hubbe)  }
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  init=(modfun)dlsym(module, "pike_module_init");
fb84a71997-03-04Henrik Grubbström (Grubba)  if (!init) { init=(modfun)dlsym(module, "_pike_module_init"); }
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  exit=(modfun)dlsym(module, "pike_module_exit");
fb84a71997-03-04Henrik Grubbström (Grubba)  if (!exit) { exit=(modfun)dlsym(module, "_pike_module_exit"); }
368fe71997-01-26Fredrik Hübinette (Hubbe)  if(!init || !exit) { dlclose(module);
14160c1998-05-15Henrik Grubbström (Grubba) 
b2b8951998-05-15Henrik Grubbström (Grubba)  if (strlen(module_name) < 1024) {
14160c1998-05-15Henrik Grubbström (Grubba)  error("Failed to initialize dynamic module \"%s\".\n", module_name); } else { error("Failed to initialize dynamic module.\n"); }
368fe71997-01-26Fredrik Hübinette (Hubbe)  } new_module=ALLOC_STRUCT(module_list); new_module->next=dynamic_module_list; dynamic_module_list=new_module; new_module->module=module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  new_module->init=init; new_module->exit=exit;
368fe71997-01-26Fredrik Hübinette (Hubbe)  pop_n_elems(args); start_new_program();
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  (*(modfun)init)(); push_program(end_program());
368fe71997-01-26Fredrik Hübinette (Hubbe) }
79f71c1998-07-09Francesco Chemolli #endif /* HAVE_DLOPEN || USE_DLD || USE_HPUX_DL */
368fe71997-01-26Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) void init_dynamic_load(void)
368fe71997-01-26Fredrik Hübinette (Hubbe) {
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
e1195f1997-03-23Fredrik Hübinette (Hubbe)  dlinit();
368fe71997-01-26Fredrik Hübinette (Hubbe)  add_efun("load_module",f_load_module,"function(string:program)",OPT_EXTERNAL_DEPEND); #endif }
be478c1997-08-30Henrik Grubbström (Grubba) void exit_dynamic_load(void)
368fe71997-01-26Fredrik Hübinette (Hubbe) {
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
368fe71997-01-26Fredrik Hübinette (Hubbe)  while(dynamic_module_list) { struct module_list *tmp=dynamic_module_list; dynamic_module_list=tmp->next;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  (*tmp->exit)();
3c0c281998-01-26Fredrik Hübinette (Hubbe) #ifndef DEBUG_MALLOC
368fe71997-01-26Fredrik Hübinette (Hubbe)  dlclose(tmp->module);
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
368fe71997-01-26Fredrik Hübinette (Hubbe)  free((char *)tmp); }
7860031997-01-22Bernhard Fastenrath #endif
368fe71997-01-26Fredrik Hübinette (Hubbe) }
e1195f1997-03-23Fredrik Hübinette (Hubbe) #else /* TESTING */ #include <stdio.h>
368fe71997-01-26Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) int main()
368fe71997-01-26Fredrik Hübinette (Hubbe) {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  void *module,*fun; dlinit(); module=dlopen("./myconftest.so",RTLD_NOW); if(!module)
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fprintf(stderr,"Failed to link myconftest.so: %s\n",dlerror()); exit(1);
a69b791996-12-28Henrik Grubbström (Grubba)  }
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fun=dlsym(module,"testfunc"); if(!fun) fun=dlsym(module,"_testfunc"); if(!fun)
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fprintf(stderr,"Failed to find function testfunc: %s\n",dlerror()); exit(1);
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  }
a991451997-07-08Fredrik Hübinette (Hubbe)  fprintf(stderr,"Calling testfunc\n");
e1195f1997-03-23Fredrik Hübinette (Hubbe)  ((void (*)(void))fun)();
a991451997-07-08Fredrik Hübinette (Hubbe)  fprintf(stderr,"testfunc returned!\n");
e1195f1997-03-23Fredrik Hübinette (Hubbe)  exit(1);
ca74dd1996-10-08Fredrik Hübinette (Hubbe) }
368fe71997-01-26Fredrik Hübinette (Hubbe) #endif