summaryrefslogtreecommitdiffstats
path: root/Python/importdl.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1995-01-02 19:04:15 (GMT)
committerGuido van Rossum <guido@python.org>1995-01-02 19:04:15 (GMT)
commit1ae940a5870df2f706fa884afd533847f6b0b1a8 (patch)
treeac19577f141b553bd56f998a62478719d5b81cd4 /Python/importdl.c
parent824de25fe2edade0ded378b4d602351272f4cf63 (diff)
downloadcpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.zip
cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.gz
cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.bz2
Lots of changes, most minor (fatal() instead of abort(), use of
err_fetch/err_restore and so on). But... NOTE: import.c has been rewritten and all the DL stuff is now in the new file importdl.c.
Diffstat (limited to 'Python/importdl.c')
-rw-r--r--Python/importdl.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/Python/importdl.c b/Python/importdl.c
new file mode 100644
index 0000000..f377c61
--- /dev/null
+++ b/Python/importdl.c
@@ -0,0 +1,381 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Support for dynamic loading of extension modules */
+/* If no dynamic linking is supported, this file still generates some code! */
+
+#include "allobjects.h"
+#include "osdefs.h"
+#include "importdl.h"
+
+extern int verbose; /* Defined in pythonrun.c */
+
+/* Explanation of some of the the various #defines used by dynamic linking...
+
+ symbol -- defined for:
+
+ DYNAMIC_LINK -- any kind of dynamic linking
+ USE_RLD -- NeXT dynamic linking
+ USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl
+ USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries
+ _AIX -- AIX style dynamic linking
+ NT -- NT style dynamic linking (using DLLs)
+ _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined
+ WITH_MAC_DL -- Mac dynamic linking (highly experimental)
+ SHORT_EXT -- short extension for dynamic module, e.g. ".so"
+ LONG_EXT -- long extension, e.g. "module.so"
+ hpux -- HP-UX Dynamic Linking - defined by the compiler
+
+ (The other WITH_* symbols are used only once, to set the
+ appropriate symbols.)
+*/
+
+/* Configure dynamic linking */
+
+#ifdef hpux
+#define DYNAMIC_LINK
+#include <errno.h>
+typedef void (*dl_funcptr)();
+#define _DL_FUNCPTR_DEFINED 1
+#define SHORT_EXT ".sl"
+#define LONG_EXT "module.sl"
+#endif
+
+#ifdef NT
+#define DYNAMIC_LINK
+#include <windows.h>
+typedef FARPROC dl_funcptr;
+#define _DL_FUNCPTR_DEFINED
+#define SHORT_EXT ".dll"
+#define LONG_EXT "module.dll"
+#endif
+
+#if defined(NeXT) || defined(WITH_RLD)
+#define DYNAMIC_LINK
+#define USE_RLD
+#endif
+
+#ifdef WITH_SGI_DL
+#define DYNAMIC_LINK
+#define USE_DL
+#endif
+
+#ifdef WITH_DL_DLD
+#define DYNAMIC_LINK
+#define USE_DL
+#endif
+
+#ifdef WITH_MAC_DL
+#define DYNAMIC_LINK
+#endif
+
+#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
+#define DYNAMIC_LINK
+#define USE_SHLIB
+#endif
+
+#ifdef _AIX
+#define DYNAMIC_LINK
+#include <sys/ldr.h>
+typedef void (*dl_funcptr)();
+#define _DL_FUNCPTR_DEFINED
+static void aix_loaderror(char *name);
+#endif
+
+#ifdef DYNAMIC_LINK
+
+#ifdef USE_SHLIB
+#include <dlfcn.h>
+#ifndef _DL_FUNCPTR_DEFINED
+typedef void (*dl_funcptr)();
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+#define SHORT_EXT ".so"
+#define LONG_EXT "module.so"
+#endif /* USE_SHLIB */
+
+#if defined(USE_DL) || defined(hpux)
+#include "dl.h"
+#endif
+
+#ifdef WITH_MAC_DL
+#include "dynamic_load.h"
+#endif
+
+#ifdef USE_RLD
+#include <mach-o/rld.h>
+#define FUNCNAME_PATTERN "_init%.200s"
+#ifndef _DL_FUNCPTR_DEFINED
+typedef void (*dl_funcptr)();
+#endif
+#endif /* USE_RLD */
+
+extern char *getprogramname();
+
+#ifndef FUNCNAME_PATTERN
+#if defined(__hp9000s300)
+#define FUNCNAME_PATTERN "_init%.200s"
+#else
+#define FUNCNAME_PATTERN "init%.200s"
+#endif
+#endif
+
+#if !defined(SHORT_EXT) && !defined(LONG_EXT)
+#define SHORT_EXT ".o"
+#define LONG_EXT "module.o"
+#endif /* !SHORT_EXT && !LONG_EXT */
+
+#endif /* DYNAMIC_LINK */
+
+/* Max length of module suffix searched for -- accommodates "module.so" */
+#ifndef MAXSUFFIXSIZE
+#define MAXSUFFIXSIZE 10
+#endif
+
+/* Pass it on to import.c */
+int import_maxsuffixsize = MAXSUFFIXSIZE;
+
+struct filedescr import_filetab[] = {
+#ifdef SHORT_EXT
+ {SHORT_EXT, "rb", C_EXTENSION},
+#endif /* !SHORT_EXT */
+#ifdef LONG_EXT
+ {LONG_EXT, "rb", C_EXTENSION},
+#endif /* !LONG_EXT */
+ {".py", "r", PY_SOURCE},
+ {".pyc", "rb", PY_COMPILED},
+ {0, 0}
+};
+
+object *
+load_dynamic_module(name, pathname)
+ char *name;
+ char *pathname;
+{
+#ifndef DYNAMIC_LINK
+ err_setstr(ImportError, "dynamically linked modules not supported");
+ return NULL;
+#else
+ object *m;
+ char funcname[258];
+ dl_funcptr p = NULL;
+ if (m != NULL) {
+ err_setstr(ImportError,
+ "cannot reload dynamically loaded module");
+ return NULL;
+ }
+ sprintf(funcname, FUNCNAME_PATTERN, name);
+#ifdef WITH_MAC_DL
+ {
+ object *v = dynamic_load(pathname);
+ if (v == NULL)
+ return NULL;
+ }
+#else /* !WITH_MAC_DL */
+#ifdef USE_SHLIB
+ {
+#ifdef RTLD_NOW
+ /* RTLD_NOW: resolve externals now
+ (i.e. core dump now if some are missing) */
+ void *handle = dlopen(pathname, RTLD_NOW);
+#else
+ void *handle;
+ if (verbose)
+ printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
+ handle = dlopen(pathname, RTLD_LAZY);
+#endif /* RTLD_NOW */
+ if (handle == NULL) {
+ err_setstr(ImportError, dlerror());
+ return NULL;
+ }
+ p = (dl_funcptr) dlsym(handle, funcname);
+ }
+#endif /* USE_SHLIB */
+#ifdef _AIX
+ p = (dl_funcptr) load(pathname, 1, 0);
+ if (p == NULL) {
+ aix_loaderror(pathname);
+ return NULL;
+ }
+#endif /* _AIX */
+#ifdef NT
+ {
+ HINSTANCE hDLL;
+ hDLL = LoadLibrary(pathname);
+ if (hDLL==NULL){
+ char errBuf[64];
+ sprintf(errBuf, "DLL load failed with error code %d",
+ GetLastError());
+ err_setstr(ImportError, errBuf);
+ return NULL;
+ }
+ p = GetProcAddress(hDLL, funcname);
+ }
+#endif /* NT */
+#ifdef USE_DL
+ p = dl_loadmod(getprogramname(), pathname, funcname);
+#endif /* USE_DL */
+#ifdef USE_RLD
+ {
+ NXStream *errorStream;
+ struct mach_header *new_header;
+ const char *filenames[2];
+ long ret;
+ unsigned long ptr;
+
+ errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
+ filenames[0] = pathname;
+ filenames[1] = NULL;
+ ret = rld_load(errorStream, &new_header,
+ filenames, NULL);
+
+ /* extract the error messages for the exception */
+ if(!ret) {
+ char *streamBuf;
+ int len, maxLen;
+
+ NXPutc(errorStream, (char)0);
+
+ NXGetMemoryBuffer(errorStream,
+ &streamBuf, &len, &maxLen);
+ err_setstr(ImportError, streamBuf);
+ }
+
+ if(ret && rld_lookup(errorStream, funcname, &ptr))
+ p = (dl_funcptr) ptr;
+
+ NXCloseMemory(errorStream, NX_FREEBUFFER);
+
+ if(!ret)
+ return NULL;
+ }
+#endif /* USE_RLD */
+#ifdef hpux
+ {
+ shl_t lib;
+ int flags;
+
+ flags = BIND_DEFERRED;
+ if (verbose)
+ {
+ flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
+ printf("shl_load %s\n",pathname);
+ }
+ lib = shl_load(pathname, flags, 0);
+ if (lib == NULL)
+ {
+ char buf[256];
+ if (verbose)
+ perror(pathname);
+ sprintf(buf, "Failed to load %.200s", pathname);
+ err_setstr(ImportError, buf);
+ return NULL;
+ }
+ if (verbose)
+ printf("shl_findsym %s\n", funcname);
+ shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
+ if (p == NULL && verbose)
+ perror(funcname);
+ }
+#endif /* hpux */
+ if (p == NULL) {
+ err_setstr(ImportError,
+ "dynamic module does not define init function");
+ return NULL;
+ }
+ (*p)();
+
+#endif /* !WITH_MAC_DL */
+ m = dictlookup(import_modules, name);
+ if (m == NULL) {
+ if (err_occurred() == NULL)
+ err_setstr(SystemError,
+ "dynamic module not initialized properly");
+ return NULL;
+ }
+ if (verbose)
+ fprintf(stderr,
+ "import %s # dynamically loaded from %s\n",
+ name, pathname);
+ INCREF(m);
+ return m;
+#endif /* DYNAMIC_LINK */
+}
+
+
+#ifdef _AIX
+
+#include <ctype.h> /* for isdigit() */
+#include <errno.h> /* for global errno */
+#include <string.h> /* for strerror() */
+
+void aix_loaderror(char *pathname)
+{
+
+ char *message[8], errbuf[1024];
+ int i,j;
+
+ struct errtab {
+ int errno;
+ char *errstr;
+ } load_errtab[] = {
+ {L_ERROR_TOOMANY, "to many errors, rest skipped."},
+ {L_ERROR_NOLIB, "can't load library:"},
+ {L_ERROR_UNDEF, "can't find symbol in library:"},
+ {L_ERROR_RLDBAD,
+ "RLD index out of range or bad relocation type:"},
+ {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
+ {L_ERROR_MEMBER,
+ "file not an archive or does not contain requested member:"},
+ {L_ERROR_TYPE, "symbol table mismatch:"},
+ {L_ERROR_ALIGN, "text allignment in file is wrong."},
+ {L_ERROR_SYSTEM, "System error:"},
+ {L_ERROR_ERRNO, NULL}
+ };
+
+#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
+#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
+
+ sprintf(errbuf, " from module %.200s ", pathname);
+
+ if (!loadquery(1, &message[0], sizeof(message)))
+ ERRBUF_APPEND(strerror(errno));
+ for(i = 0; message[i] && *message[i]; i++) {
+ int nerr = atoi(message[i]);
+ for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
+ if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
+ ERRBUF_APPEND(load_errtab[i].errstr);
+ }
+ while (isdigit(*message[i])) message[i]++ ;
+ ERRBUF_APPEND(message[i]);
+ ERRBUF_APPEND("\n");
+ }
+ errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
+ err_setstr(ImportError, errbuf);
+ return;
+}
+
+#endif /* _AIX */