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