dynload_shlib.c 3.21 KB
Newer Older
1 2 3 4 5 6 7 8

/* Support for dynamic loading of extension modules */

#include "Python.h"
#include "importdl.h"

#include <sys/types.h>
#include <sys/stat.h>
9

10 11 12
#if defined(__NetBSD__)
#include <sys/param.h>
#if (NetBSD < 199712)
13 14 15
#include <nlist.h>
#include <link.h>
#define dlerror() "error in dynamic linking"
16 17 18
#endif
#endif /* NetBSD */

19 20
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
21 22 23 24
#else
#if defined(PYOS_OS2) && defined(PYCC_GCC)
#include "dlfcn.h"
#endif
25 26
#endif

27
#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
28 29 30 31 32
#define LEAD_UNDERSCORE "_"
#else
#define LEAD_UNDERSCORE ""
#endif

33 34

const struct filedescr _PyImport_DynLoadFiletab[] = {
35 36
#ifdef __CYGWIN__
	{".dll", "rb", C_EXTENSION},
37
	{"module.dll", "rb", C_EXTENSION},
38 39 40 41
#else
#if defined(PYOS_OS2) && defined(PYCC_GCC)
	{".pyd", "rb", C_EXTENSION},
	{".dll", "rb", C_EXTENSION},
42 43 44 45 46 47
#else
#ifdef __VMS
        {".exe", "rb", C_EXTENSION},
        {".EXE", "rb", C_EXTENSION},
        {"module.exe", "rb", C_EXTENSION},
        {"MODULE.EXE", "rb", C_EXTENSION},
48
#else
49 50
	{".so", "rb", C_EXTENSION},
	{"module.so", "rb", C_EXTENSION},
51
#endif
52
#endif
53
#endif
54 55 56 57 58
	{0, 0}
};

static struct {
	dev_t dev;
59 60 61
#ifdef __VMS
	ino_t ino[3];
#else
62
	ino_t ino;
63
#endif
64 65 66 67 68
	void *handle;
} handles[128];
static int nhandles = 0;


69
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
70 71 72 73
				    const char *pathname, FILE *fp)
{
	dl_funcptr p;
	void *handle;
74 75
	char funcname[258];
	char pathbuf[260];
76
        int dlopenflags=0;
77 78 79

	if (strchr(pathname, '/') == NULL) {
		/* Prefix bare filename with "./" */
80
		PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
81 82 83
		pathname = pathbuf;
	}

84 85
	PyOS_snprintf(funcname, sizeof(funcname), 
		      LEAD_UNDERSCORE "init%.200s", shortname);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

	if (fp != NULL) {
		int i;
		struct stat statb;
		fstat(fileno(fp), &statb);
		for (i = 0; i < nhandles; i++) {
			if (statb.st_dev == handles[i].dev &&
			    statb.st_ino == handles[i].ino) {
				p = (dl_funcptr) dlsym(handles[i].handle,
						       funcname);
				return p;
			}
		}
		if (nhandles < 128) {
			handles[nhandles].dev = statb.st_dev;
101 102 103 104 105
#ifdef __VMS
			handles[nhandles].ino[0] = statb.st_ino[0];
			handles[nhandles].ino[1] = statb.st_ino[1];
			handles[nhandles].ino[2] = statb.st_ino[2];
#else
106
			handles[nhandles].ino = statb.st_ino;
107
#endif
108 109 110
		}
	}

111
#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
112
        dlopenflags = PyThreadState_GET()->interp->dlopenflags;
113
#endif
114

115
	if (Py_VerboseFlag)
116 117
		PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, 
				  dlopenflags);
118

119 120 121 122 123 124 125 126 127 128 129
#ifdef __VMS
	/* VMS currently don't allow a pathname, use a logical name instead */
	/* Concatenate 'python_module_' and shortname */
	/* so "import vms.bar" will use the logical python_module_bar */
	/* As C module use only one name space this is probably not a */
	/* important limitation */
	PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s", 
		      shortname);
	pathname = pathbuf;
#endif

130 131
	handle = dlopen(pathname, dlopenflags);

132
	if (handle == NULL) {
133
		const char *error = dlerror();
134 135 136
		if (error == NULL)
			error = "unknown dlopen() error";
		PyErr_SetString(PyExc_ImportError, error);
137 138 139 140 141 142 143
		return NULL;
	}
	if (fp != NULL && nhandles < 128)
		handles[nhandles++].handle = handle;
	p = (dl_funcptr) dlsym(handle, funcname);
	return p;
}