Python-2.7.3/Modules/dlmodule.c

No issues found

  1 /* dl module */
  2 
  3 #include "Python.h"
  4 
  5 #include <dlfcn.h>
  6 
  7 #ifdef __VMS
  8 #include <unistd.h>
  9 #endif
 10 
 11 #ifndef RTLD_LAZY
 12 #define RTLD_LAZY 1
 13 #endif
 14 
 15 typedef void *PyUnivPtr;
 16 typedef struct {
 17     PyObject_HEAD
 18     PyUnivPtr *dl_handle;
 19 } dlobject;
 20 
 21 static PyTypeObject Dltype;
 22 
 23 static PyObject *Dlerror;
 24 
 25 static PyObject *
 26 newdlobject(PyUnivPtr *handle)
 27 {
 28     dlobject *xp;
 29     xp = PyObject_New(dlobject, &Dltype);
 30     if (xp == NULL)
 31         return NULL;
 32     xp->dl_handle = handle;
 33     return (PyObject *)xp;
 34 }
 35 
 36 static void
 37 dl_dealloc(dlobject *xp)
 38 {
 39     if (xp->dl_handle != NULL)
 40         dlclose(xp->dl_handle);
 41     PyObject_Del(xp);
 42 }
 43 
 44 static PyObject *
 45 dl_close(dlobject *xp)
 46 {
 47     if (xp->dl_handle != NULL) {
 48         dlclose(xp->dl_handle);
 49         xp->dl_handle = NULL;
 50     }
 51     Py_INCREF(Py_None);
 52     return Py_None;
 53 }
 54 
 55 static PyObject *
 56 dl_sym(dlobject *xp, PyObject *args)
 57 {
 58     char *name;
 59     PyUnivPtr *func;
 60     if (PyString_Check(args)) {
 61         name = PyString_AS_STRING(args);
 62     } else {
 63         PyErr_Format(PyExc_TypeError, "expected string, found %.200s",
 64                      Py_TYPE(args)->tp_name);
 65         return NULL;
 66     }
 67     func = dlsym(xp->dl_handle, name);
 68     if (func == NULL) {
 69         Py_INCREF(Py_None);
 70         return Py_None;
 71     }
 72     return PyInt_FromLong((long)func);
 73 }
 74 
 75 static PyObject *
 76 dl_call(dlobject *xp, PyObject *args)
 77 {
 78     PyObject *name;
 79     long (*func)(long, long, long, long, long,
 80                  long, long, long, long, long);
 81     long alist[10];
 82     long res;
 83     Py_ssize_t i;
 84     Py_ssize_t n = PyTuple_Size(args);
 85     if (n < 1) {
 86         PyErr_SetString(PyExc_TypeError, "at least a name is needed");
 87         return NULL;
 88     }
 89     name = PyTuple_GetItem(args, 0);
 90     if (!PyString_Check(name)) {
 91         PyErr_SetString(PyExc_TypeError,
 92                         "function name must be a string");
 93         return NULL;
 94     }
 95     func = (long (*)(long, long, long, long, long,
 96                      long, long, long, long, long))
 97       dlsym(xp->dl_handle, PyString_AsString(name));
 98     if (func == NULL) {
 99         PyErr_SetString(PyExc_ValueError, dlerror());
100         return NULL;
101     }
102     if (n-1 > 10) {
103         PyErr_SetString(PyExc_TypeError,
104                         "too many arguments (max 10)");
105         return NULL;
106     }
107     for (i = 1; i < n; i++) {
108         PyObject *v = PyTuple_GetItem(args, i);
109         if (PyInt_Check(v))
110             alist[i-1] = PyInt_AsLong(v);
111         else if (PyString_Check(v))
112             alist[i-1] = (long)PyString_AsString(v);
113         else if (v == Py_None)
114             alist[i-1] = (long) ((char *)NULL);
115         else {
116             PyErr_SetString(PyExc_TypeError,
117                        "arguments must be int, string or None");
118             return NULL;
119         }
120     }
121     for (; i <= 10; i++)
122         alist[i-1] = 0;
123     res = (*func)(alist[0], alist[1], alist[2], alist[3], alist[4],
124                   alist[5], alist[6], alist[7], alist[8], alist[9]);
125     return PyInt_FromLong(res);
126 }
127 
128 static PyMethodDef dlobject_methods[] = {
129     {"call",            (PyCFunction)dl_call, METH_VARARGS},
130     {"sym",             (PyCFunction)dl_sym, METH_O},
131     {"close",           (PyCFunction)dl_close, METH_NOARGS},
132     {NULL,              NULL}                    /* Sentinel */
133 };
134 
135 static PyObject *
136 dl_getattr(dlobject *xp, char *name)
137 {
138     return Py_FindMethod(dlobject_methods, (PyObject *)xp, name);
139 }
140 
141 
142 static PyTypeObject Dltype = {
143     PyVarObject_HEAD_INIT(NULL, 0)
144     "dl.dl",                    /*tp_name*/
145     sizeof(dlobject),           /*tp_basicsize*/
146     0,                          /*tp_itemsize*/
147     /* methods */
148     (destructor)dl_dealloc, /*tp_dealloc*/
149     0,                          /*tp_print*/
150     (getattrfunc)dl_getattr,/*tp_getattr*/
151     0,                          /*tp_setattr*/
152     0,                          /*tp_compare*/
153     0,                          /*tp_repr*/
154     0,                          /*tp_as_number*/
155     0,                          /*tp_as_sequence*/
156     0,                          /*tp_as_mapping*/
157     0,                          /*tp_hash*/
158 };
159 
160 static PyObject *
161 dl_open(PyObject *self, PyObject *args)
162 {
163     char *name;
164     int mode;
165     PyUnivPtr *handle;
166     if (sizeof(int) != sizeof(long) ||
167         sizeof(long) != sizeof(char *)) {
168         PyErr_SetString(PyExc_SystemError,
169  "module dl requires sizeof(int) == sizeof(long) == sizeof(char*)");
170                 return NULL;
171     }
172 
173     if (PyArg_ParseTuple(args, "z:open", &name))
174         mode = RTLD_LAZY;
175     else {
176         PyErr_Clear();
177         if (!PyArg_ParseTuple(args, "zi:open", &name, &mode))
178             return NULL;
179 #ifndef RTLD_NOW
180         if (mode != RTLD_LAZY) {
181             PyErr_SetString(PyExc_ValueError, "mode must be 1");
182             return NULL;
183         }
184 #endif
185     }
186     handle = dlopen(name, mode);
187     if (handle == NULL) {
188         char *errmsg = dlerror();
189         if (!errmsg)
190             errmsg = "dlopen() error";
191         PyErr_SetString(Dlerror, errmsg);
192         return NULL;
193     }
194 #ifdef __VMS
195     /*   Under OpenVMS dlopen doesn't do any check, just save the name
196      * for later use, so we have to check if the file is readable,
197      * the name can be a logical or a file from SYS$SHARE.
198      */
199     if (access(name, R_OK)) {
200         char fname[strlen(name) + 20];
201         strcpy(fname, "SYS$SHARE:");
202         strcat(fname, name);
203         strcat(fname, ".EXE");
204         if (access(fname, R_OK)) {
205             dlclose(handle);
206             PyErr_SetString(Dlerror,
207                 "File not found or protection violation");
208             return NULL;
209         }
210     }
211 #endif
212     return newdlobject(handle);
213 }
214 
215 static PyMethodDef dl_methods[] = {
216     {"open",            dl_open, METH_VARARGS},
217     {NULL,              NULL}           /* sentinel */
218 };
219 
220 /* From socketmodule.c
221  * Convenience routine to export an integer value.
222  *
223  * Errors are silently ignored, for better or for worse...
224  */
225 static void
226 insint(PyObject *d, char *name, int value)
227 {
228     PyObject *v = PyInt_FromLong((long) value);
229     if (!v || PyDict_SetItemString(d, name, v))
230         PyErr_Clear();
231 
232     Py_XDECREF(v);
233 }
234 
235 PyMODINIT_FUNC
236 initdl(void)
237 {
238     PyObject *m, *d, *x;
239 
240     if (PyErr_WarnPy3k("the dl module has been removed in "
241                         "Python 3.0; use the ctypes module instead", 2) < 0)
242     return;
243 
244     /* Initialize object type */
245     Py_TYPE(&Dltype) = &PyType_Type;
246 
247     /* Create the module and add the functions */
248     m = Py_InitModule("dl", dl_methods);
249     if (m == NULL)
250         return;
251 
252     /* Add some symbolic constants to the module */
253     d = PyModule_GetDict(m);
254     Dlerror = x = PyErr_NewException("dl.error", NULL, NULL);
255     PyDict_SetItemString(d, "error", x);
256     x = PyInt_FromLong((long)RTLD_LAZY);
257     PyDict_SetItemString(d, "RTLD_LAZY", x);
258 #define INSINT(X)    insint(d,#X,X)
259 #ifdef RTLD_NOW
260     INSINT(RTLD_NOW);
261 #endif
262 #ifdef RTLD_NOLOAD
263     INSINT(RTLD_NOLOAD);
264 #endif
265 #ifdef RTLD_GLOBAL
266     INSINT(RTLD_GLOBAL);
267 #endif
268 #ifdef RTLD_LOCAL
269     INSINT(RTLD_LOCAL);
270 #endif
271 #ifdef RTLD_PARENT
272     INSINT(RTLD_PARENT);
273 #endif
274 #ifdef RTLD_GROUP
275     INSINT(RTLD_GROUP);
276 #endif
277 #ifdef RTLD_WORLD
278     INSINT(RTLD_WORLD);
279 #endif
280 #ifdef RTLD_NODELETE
281     INSINT(RTLD_NODELETE);
282 #endif
283 }