Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • 9.0
  • 8.0
  • 7.8
  • 7.6
  • 7.4
  • 7.2
  • 7.0
  • 0.6
  • rosuav/latex-markdown-renderer
  • rxnpatch/rxnpatch
  • marcus/gobject-introspection
  • rxnpatch/8.0
  • rosuav/pre-listening-ports
  • nt-tools
  • rosuav/async-annotations
  • rosuav/pgsql-ssl
  • rxnpatch/rxnpatch-broken/2023-10-06T094250
  • grubba/fdlib
  • grubba/wip/sakura/8.0
  • v8.0.1994
  • v8.0.1992
  • v8.0.1990
  • v8.0.1988
  • v8.0.1986
  • rxnpatch/clusters/8.0/2025-04-29T124414
  • rxnpatch/2025-04-29T124414
  • v8.0.1984
  • v8.0.1982
  • v8.0.1980
  • v8.0.1978
  • v8.0.1976
  • v8.0.1974
  • v8.0.1972
  • v8.0.1970
  • v8.0.1968
  • v8.0.1966
  • v8.0.1964
  • v8.0.1962
  • v8.0.1960
40 results

dynamic_load.c

Blame
    • Henrik (Grubba) Grubbström's avatar
      8c953aca
      tPrg is now an inner type-node. · 8c953aca
      Henrik (Grubba) Grubbström authored
      Rev: src/builtin_functions.c:1.356
      Rev: src/dynamic_load.c:1.52
      Rev: src/encode.c:1.94
      Rev: src/language.yacc:1.235
      Rev: src/modules/Image/image_module.c:1.10
      Rev: src/modules/PDF/pdf_module.c:1.8
      Rev: src/modules/_Crypto/cbc.c:1.20
      Rev: src/modules/_Crypto/crypto.c:1.44
      Rev: src/modules/_Crypto/pipe.c:1.21
      Rev: src/modules/files/stat.c:1.16
      Rev: src/modules/spider/spider.c:1.104
      Rev: src/operators.c:1.133
      Rev: src/svalue.h:1.85
      8c953aca
      History
      tPrg is now an inner type-node.
      Henrik (Grubba) Grubbström authored
      Rev: src/builtin_functions.c:1.356
      Rev: src/dynamic_load.c:1.52
      Rev: src/encode.c:1.94
      Rev: src/language.yacc:1.235
      Rev: src/modules/Image/image_module.c:1.10
      Rev: src/modules/PDF/pdf_module.c:1.8
      Rev: src/modules/_Crypto/cbc.c:1.20
      Rev: src/modules/_Crypto/crypto.c:1.44
      Rev: src/modules/_Crypto/pipe.c:1.21
      Rev: src/modules/files/stat.c:1.16
      Rev: src/modules/spider/spider.c:1.104
      Rev: src/operators.c:1.133
      Rev: src/svalue.h:1.85
    dynamic_load.c 8.29 KiB
    #ifndef TESTING
    #  include "global.h"
    #  include "interpret.h"
    #  include "constants.h"
    #  include "pike_error.h"
    #  include "module.h"
    #  include "stralloc.h"
    #  include "pike_macros.h"
    #  include "main.h"
    
    RCSID("$Id: dynamic_load.c,v 1.52 2001/03/28 15:07:38 grubba Exp $");
    
    #endif /* !TESTING */
    
    #ifdef HAVE_ERRNO_H
    #include <errno.h>
    #endif /* HAVE_ERRNO_H */
    #ifdef HAVE_STRING_H
    #include <string.h>
    #endif /* HAVE_STRING_H */
    
    #if !defined(HAVE_DLOPEN)
    
    #if defined(HAVE_DLD_LINK) && defined(HAVE_DLD_GET_FUNC)
    #define USE_DLD
    #define HAVE_SOME_DLOPEN
    #define EMULATE_DLOPEN
    #else
    #if defined(HAVE_SHL_LOAD) && defined(HAVE_DL_H)
    #define USE_HPUX_DL
    #define HAVE_SOME_DLOPEN
    #define EMULATE_DLOPEN
    #else
    
    #if 0
    #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 /* 0 */
    
    #ifdef USE_MY_WIN32_DLOPEN
    #include "pike_dlfcn.h"
    #define HAVE_SOME_DLOPEN
    #define HAVE_DLOPEN
    #endif
    
    #endif
    #endif
    #else
    #define HAVE_SOME_DLOPEN
    #endif
    
    
    #ifdef HAVE_SOME_DLOPEN
    
    typedef void (*modfun)(void);
    
    #ifdef USE_LOADLIBRARY
    #include <windows.h>
    
    static TCHAR *convert_string(const char *str, ptrdiff_t len)
    {
      ptrdiff_t 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(const char *foo, int how)
    {
      TCHAR *tmp;
      HINSTANCE ret;
      tmp=convert_string(foo, strlen(foo));
      ret=LoadLibrary(tmp);
      free((char *)tmp);
      if(ret)
      {
        void ** psym=(void **)GetProcAddress(ret, "PikeSymbol");
        if(psym)
        {
          extern void *PikeSymbol[];
          *psym = PikeSymbol;
        }
      }
      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()
    
    #endif /* USE_LOADLIBRARY */
    
    
    #ifdef USE_DLD
    #include <dld.h>
    static void *dlopen(const char *module_name, int how)
    {
      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);
      }
    }
    
    #endif /* USE_DLD */
    
    
    #ifdef USE_HPUX_DL
    
    #include <dl.h>
    
    #if defined(BIND_VERBOSE)
    #define RTLD_NOW	BIND_IMMEDIATE | BIND_VERBOSE
    #else
    #define RTLD_NOW	BIND_IMMEDIATE
    #endif /* BIND_VERBOSE */
    
    extern int errno;
    
    static void *dlopen(const char *libname, int how)
    {
      shl_t lib;
    
      lib = shl_load(libname, how, 0L);
    
      return (void *)lib;
    }
    
    static char *dlerror(void)
    {
    #ifdef HAVE_STRERROR
      return strerror(errno);
    #else
      return ""; /* I hope it's better than null..*/
    #endif
    }
    
    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 */
    
    
    #ifndef EMULATE_DLOPEN
    
    #ifdef HAVE_DLFCN_H
    #include <dlfcn.h>
    #endif
    
    #define dlinit()
    #endif  /* !EMULATE_DLOPEN */
    
    
    #endif /* HAVE_SOME_DLOPEN */
    
    #ifndef RTLD_NOW
    #define RTLD_NOW 0
    #endif
    
    #ifndef RTLD_LAZY
    #define RTLD_LAZY 0
    #endif
    
    #ifndef RTLD_GLOBAL
    #define RTLD_GLOBAL 0 
    #endif
    
    #ifndef TESTING
    
    #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL) || defined(USE_LOADLIBRARY)
    #define USE_DYNAMIC_MODULES
    #endif
    
    #ifdef USE_DYNAMIC_MODULES
    
    struct module_list
    {
      struct module_list * next;
      void *module;
      modfun init, exit;
    };
    
    struct module_list *dynamic_module_list = 0;
    
    #ifdef NO_CAST_TO_FUN
    /* Function pointers can't be casted to scalar pointers according to
     * ISO-C (probably to support true Harward achitecture machines).
     */
    static modfun CAST_TO_FUN(void *ptr)
    {
      union {
        void *ptr;
        modfun fun;
      } u;
      u.ptr = ptr;
      return u.fun;
    }
    #else /* !NO_CAST_TO_FUN */
    #define CAST_TO_FUN(X)	((modfun)X)
    #endif /* NO_CAST_TO_FUN */
    
    /*! @decl int load_module(string module_name)
     *!
     *! Load a binary module.
     *!
     *! This function loads a module written in C or some other language
     *! into Pike. The module is initialized and any programs or constants
     *! defined will immediately be available.
     *!
     *! When a module is loaded the function @tt{pike_module_init()@} will
     *! be called to initialize it. When Pike exits @tt{pike_module_exit()@}
     *! will be called. These two functions @b{must@} be available in the module.
     *!
     *! @note
     *!   The current working directory is normally not searched for
     *!   dynamic modules. Please use @tt{"./name.so"@} instead of just
     *!   @tt{"name.so"@} to load modules from the current directory.
     */
    void f_load_module(INT32 args)
    {
      void *module;
      modfun init, exit;
      struct module_list *new_module;
      const char *module_name;
    
      if(sp[-args].type != T_STRING)
        Pike_error("Bad argument 1 to load_module()\n");
    
      module_name = sp[-args].u.string->str;
    
      /* Removing RTLD_GLOBAL breaks some PiGTK themes - Hubbe */
      /* Using RTLD_LAZY is faster, but makes it impossible to 
       * detect linking problems at runtime..
       */
      module=dlopen(module_name, 
                    RTLD_NOW |RTLD_GLOBAL  );
    
      if(!module)
      {
        const char *err = dlerror();
        if(!err) err = "Unknown reason";
        if (sp[-args].u.string->len < 1024) {
          Pike_error("load_module(\"%s\") failed: %s\n",
    	    sp[-args].u.string->str, err);
        } else {
          Pike_error("load_module() failed: %s\n", err);
        }
      }
    
      init = CAST_TO_FUN(dlsym(module, "pike_module_init"));
      if (!init) {
        init = CAST_TO_FUN(dlsym(module, "_pike_module_init"));
      }
      exit = CAST_TO_FUN(dlsym(module, "pike_module_exit"));
      if (!exit) {
        exit = CAST_TO_FUN(dlsym(module, "_pike_module_exit"));
      }
    
      if(!init || !exit)
      {
        dlclose(module);
    
        if (strlen(module_name) < 1024) {
          Pike_error("Failed to initialize dynamic module \"%s\".\n", module_name);
        } else {
          Pike_error("Failed to initialize dynamic 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->init=init;
      new_module->exit=exit;
    
      start_new_program();
    #ifdef PIKE_DEBUG
      { struct svalue *save_sp=sp;
    #endif
      (*(modfun)init)();
    #ifdef PIKE_DEBUG
      if(sp != save_sp)
        fatal("load_module(%s) left %ld droppings on stack!\n",
    	  module_name,
    	  PTRDIFF_T_TO_LONG(sp - save_sp));
      }
    #endif
    
      pop_n_elems(args);
      push_program(end_program());
    }
    
    #endif /* USE_DYNAMIC_MODULES */
    
    
    void init_dynamic_load(void)
    {
    #ifdef USE_DYNAMIC_MODULES
      dlinit();
    
      
    /* function(string:program) */
    
      ADD_EFUN("load_module",f_load_module,tFunc(tStr,tPrg(tObj)),OPT_EXTERNAL_DEPEND);
    #endif
    }
    
    /* Call the pike_module_exit() callbacks for the dynamic modules. */
    void exit_dynamic_load(void)
    {
    #ifdef USE_DYNAMIC_MODULES
      struct module_list *tmp;
      for (tmp = dynamic_module_list; tmp; tmp = tmp->next)
        (*tmp->exit)();
    #endif
    }
    
    /* Unload all the dynamically loaded modules. */
    void free_dynamic_load(void)
    {
    #ifdef USE_DYNAMIC_MODULES
      while(dynamic_module_list)
      {
        struct module_list *tmp=dynamic_module_list;
        dynamic_module_list=tmp->next;
    #ifndef DEBUG_MALLOC
        dlclose(tmp->module);
    #endif
        free((char *)tmp);
      }
    #endif
    }
    
    
    #else /* TESTING */
    #include <stdio.h>
    
    int main()
    {
      void *module,*fun;
      dlinit();
      module=dlopen("./myconftest.so",RTLD_NOW);
      if(!module)
      {
        fprintf(stderr,"Failed to link myconftest.so: %s\n",dlerror());
        exit(1);
      }
      fun=dlsym(module,"testfunc");
      if(!fun) fun=dlsym(module,"_testfunc");
      if(!fun)
      {
        fprintf(stderr,"Failed to find function testfunc: %s\n",dlerror());
        exit(1);
      }
      fprintf(stderr,"Calling testfunc\n");
      ((void (*)(void))fun)();
      fprintf(stderr,"testfunc returned!\n");
      exit(1);
    }
    #endif