Line data Source code
1 :
2 : /* Support for dynamic loading of extension modules */
3 :
4 : #include "Python.h"
5 : #include "importdl.h"
6 :
7 : #include <sys/types.h>
8 : #include <sys/stat.h>
9 :
10 : #if defined(__NetBSD__)
11 : #include <sys/param.h>
12 : #if (NetBSD < 199712)
13 : #include <nlist.h>
14 : #include <link.h>
15 : #define dlerror() "error in dynamic linking"
16 : #endif
17 : #endif /* NetBSD */
18 :
19 : #ifdef HAVE_DLFCN_H
20 : #include <dlfcn.h>
21 : #else
22 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
23 : #include "dlfcn.h"
24 : #endif
25 : #endif
26 :
27 : #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
28 : #define LEAD_UNDERSCORE "_"
29 : #else
30 : #define LEAD_UNDERSCORE ""
31 : #endif
32 :
33 :
34 : const struct filedescr _PyImport_DynLoadFiletab[] = {
35 : #ifdef __CYGWIN__
36 : {".dll", "rb", C_EXTENSION},
37 : {"module.dll", "rb", C_EXTENSION},
38 : #else
39 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
40 : {".pyd", "rb", C_EXTENSION},
41 : {".dll", "rb", C_EXTENSION},
42 : #else
43 : #ifdef __VMS
44 : {".exe", "rb", C_EXTENSION},
45 : {".EXE", "rb", C_EXTENSION},
46 : {"module.exe", "rb", C_EXTENSION},
47 : {"MODULE.EXE", "rb", C_EXTENSION},
48 : #else
49 : {".so", "rb", C_EXTENSION},
50 : {"module.so", "rb", C_EXTENSION},
51 : #endif
52 : #endif
53 : #endif
54 : {0, 0}
55 : };
56 :
57 : static struct {
58 : dev_t dev;
59 : #ifdef __VMS
60 : ino_t ino[3];
61 : #else
62 : ino_t ino;
63 : #endif
64 : void *handle;
65 : } handles[128];
66 : static int nhandles = 0;
67 :
68 :
69 54 : dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
70 : const char *pathname, FILE *fp)
71 : {
72 : dl_funcptr p;
73 : void *handle;
74 : char funcname[258];
75 : char pathbuf[260];
76 54 : int dlopenflags=0;
77 :
78 : /* DISABLING FOR OIL */
79 : #ifdef DISABLE_DLOPEN_FOR_OIL
80 : printf("GetDynLoadFunc fq:%s short:%s path:%s -> DISABLED\n",
81 : fqname, shortname, pathname);
82 : PyErr_SetString(PyExc_ImportError, "Oil doesn't allow dynamic modules");
83 : return NULL;
84 : #endif
85 :
86 54 : if (strchr(pathname, '/') == NULL) {
87 : /* Prefix bare filename with "./" */
88 0 : PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
89 0 : pathname = pathbuf;
90 : }
91 :
92 54 : PyOS_snprintf(funcname, sizeof(funcname),
93 : LEAD_UNDERSCORE "init%.200s", shortname);
94 :
95 54 : if (fp != NULL) {
96 : int i;
97 : struct stat statb;
98 54 : fstat(fileno(fp), &statb);
99 513 : for (i = 0; i < nhandles; i++) {
100 918 : if (statb.st_dev == handles[i].dev &&
101 459 : statb.st_ino == handles[i].ino) {
102 0 : p = (dl_funcptr) dlsym(handles[i].handle,
103 : funcname);
104 0 : return p;
105 : }
106 : }
107 54 : if (nhandles < 128) {
108 54 : handles[nhandles].dev = statb.st_dev;
109 : #ifdef __VMS
110 : handles[nhandles].ino[0] = statb.st_ino[0];
111 : handles[nhandles].ino[1] = statb.st_ino[1];
112 : handles[nhandles].ino[2] = statb.st_ino[2];
113 : #else
114 54 : handles[nhandles].ino = statb.st_ino;
115 : #endif
116 : }
117 : }
118 :
119 : #if !(defined(PYOS_OS2) && defined(PYCC_GCC))
120 54 : dlopenflags = PyThreadState_GET()->interp->dlopenflags;
121 : #endif
122 :
123 54 : if (Py_VerboseFlag)
124 0 : PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
125 : dlopenflags);
126 :
127 : #ifdef __VMS
128 : /* VMS currently don't allow a pathname, use a logical name instead */
129 : /* Concatenate 'python_module_' and shortname */
130 : /* so "import vms.bar" will use the logical python_module_bar */
131 : /* As C module use only one name space this is probably not a */
132 : /* important limitation */
133 : PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
134 : shortname);
135 : pathname = pathbuf;
136 : #endif
137 :
138 54 : handle = dlopen(pathname, dlopenflags);
139 :
140 54 : if (handle == NULL) {
141 0 : const char *error = dlerror();
142 0 : if (error == NULL)
143 0 : error = "unknown dlopen() error";
144 0 : PyErr_SetString(PyExc_ImportError, error);
145 0 : return NULL;
146 : }
147 54 : if (fp != NULL && nhandles < 128)
148 54 : handles[nhandles++].handle = handle;
149 54 : p = (dl_funcptr) dlsym(handle, funcname);
150 54 : return p;
151 : }
|