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 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