PageRenderTime 29ms CodeModel.GetById 10ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/Modules/dlmodule.c

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