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 
_PyImport_GetDynLoadFunc(const char * fqname,const char * shortname,const char * pathname,FILE * fp)69 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     int dlopenflags=0;
77 
78     if (strchr(pathname, '/') == NULL) {
79         /* Prefix bare filename with "./" */
80         PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
81         pathname = pathbuf;
82     }
83 
84     PyOS_snprintf(funcname, sizeof(funcname),
85                   LEAD_UNDERSCORE "init%.200s", shortname);
86 
87     if (fp != NULL) {
88         int i;
89         struct stat statb;
90         fstat(fileno(fp), &statb);
91         for (i = 0; i < nhandles; i++) {
92             if (statb.st_dev == handles[i].dev &&
93                 statb.st_ino == handles[i].ino) {
94                 p = (dl_funcptr) dlsym(handles[i].handle,
95                                        funcname);
96                 return p;
97             }
98         }
99         if (nhandles < 128) {
100             handles[nhandles].dev = statb.st_dev;
101 #ifdef __VMS
102             handles[nhandles].ino[0] = statb.st_ino[0];
103             handles[nhandles].ino[1] = statb.st_ino[1];
104             handles[nhandles].ino[2] = statb.st_ino[2];
105 #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         PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
117                           dlopenflags);
118 
119 #ifdef __VMS
120     /* VMS currently don't allow a pathname, use a logical name instead */
121     /* Concatenate 'python_module_' and shortname */
122     /* so "import vms.bar" will use the logical python_module_bar */
123     /* As C module use only one name space this is probably not a */
124     /* important limitation */
125     PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
126                   shortname);
127     pathname = pathbuf;
128 #endif
129 
130     handle = dlopen(pathname, dlopenflags);
131 
132     if (handle == NULL) {
133         const char *error = dlerror();
134         if (error == NULL)
135             error = "unknown dlopen() error";
136         PyErr_SetString(PyExc_ImportError, error);
137         return NULL;
138     }
139     if (fp != NULL && nhandles < 128)
140         handles[nhandles++].handle = handle;
141     p = (dl_funcptr) dlsym(handle, funcname);
142     return p;
143 }
144