| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 1 |  | 
 | 2 | /* dl module */ | 
 | 3 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 4 | #include "Python.h" | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 5 |  | 
 | 6 | #include <dlfcn.h> | 
 | 7 |  | 
 | 8 | #ifndef RTLD_LAZY | 
 | 9 | #define RTLD_LAZY 1 | 
 | 10 | #endif | 
 | 11 |  | 
| Thomas Wouters | 334fb89 | 2000-07-25 12:56:38 +0000 | [diff] [blame] | 12 | typedef void *PyUnivPtr; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 13 | typedef struct { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 14 | 	PyObject_HEAD | 
 | 15 | 	PyUnivPtr *dl_handle; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 16 | } dlobject; | 
 | 17 |  | 
| Jeremy Hylton | 938ace6 | 2002-07-17 16:30:39 +0000 | [diff] [blame] | 18 | static PyTypeObject Dltype; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 19 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 20 | static PyObject *Dlerror; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 21 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 22 | static PyObject * | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 23 | newdlobject(PyUnivPtr *handle) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 24 | { | 
 | 25 | 	dlobject *xp; | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 26 | 	xp = PyObject_New(dlobject, &Dltype); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 27 | 	if (xp == NULL) | 
 | 28 | 		return NULL; | 
 | 29 | 	xp->dl_handle = handle; | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 30 | 	return (PyObject *)xp; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 31 | } | 
 | 32 |  | 
 | 33 | static void | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 34 | dl_dealloc(dlobject *xp) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 35 | { | 
 | 36 | 	if (xp->dl_handle != NULL) | 
 | 37 | 		dlclose(xp->dl_handle); | 
| Guido van Rossum | b18618d | 2000-05-03 23:44:39 +0000 | [diff] [blame] | 38 | 	PyObject_Del(xp); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 39 | } | 
 | 40 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 41 | static PyObject * | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 42 | dl_close(dlobject *xp) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 43 | { | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 44 | 	if (xp->dl_handle != NULL) { | 
 | 45 | 		dlclose(xp->dl_handle); | 
 | 46 | 		xp->dl_handle = NULL; | 
 | 47 | 	} | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 48 | 	Py_INCREF(Py_None); | 
 | 49 | 	return Py_None; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 50 | } | 
 | 51 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 52 | static PyObject * | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 53 | dl_sym(dlobject *xp, PyObject *args) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 54 | { | 
 | 55 | 	char *name; | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 56 | 	PyUnivPtr *func; | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 57 | 	if (PyString_Check(args)) { | 
 | 58 | 		name = PyString_AS_STRING(args); | 
 | 59 | 	} else { | 
 | 60 | 		PyErr_Format(PyExc_TypeError, "expected string, found %.200s", | 
 | 61 | 			     args->ob_type->tp_name); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 62 | 		return NULL; | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 63 | 	} | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 64 | 	func = dlsym(xp->dl_handle, name); | 
 | 65 | 	if (func == NULL) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 66 | 		Py_INCREF(Py_None); | 
 | 67 | 		return Py_None; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 68 | 	} | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 69 | 	return PyInt_FromLong((long)func); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 70 | } | 
 | 71 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 72 | static PyObject * | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 73 | dl_call(dlobject *xp, PyObject *args) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 74 | { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 75 | 	PyObject *name; | 
| Fred Drake | 4747a18 | 2000-10-11 21:44:02 +0000 | [diff] [blame] | 76 | 	long (*func)(long, long, long, long, long, | 
 | 77 |                      long, long, long, long, long); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 78 | 	long alist[10]; | 
 | 79 | 	long res; | 
 | 80 | 	int i; | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 81 | 	int n = PyTuple_Size(args); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 82 | 	if (n < 1) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 83 | 		PyErr_SetString(PyExc_TypeError, "at least a name is needed"); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 84 | 		return NULL; | 
 | 85 | 	} | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 86 | 	name = PyTuple_GetItem(args, 0); | 
 | 87 | 	if (!PyString_Check(name)) { | 
 | 88 | 		PyErr_SetString(PyExc_TypeError, | 
 | 89 | 				"function name must be a string"); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 90 | 		return NULL; | 
 | 91 | 	} | 
| Andrew M. Kuchling | a1a690f | 2001-02-22 15:52:55 +0000 | [diff] [blame] | 92 | 	func = (long (*)(long, long, long, long, long,  | 
 | 93 |                          long, long, long, long, long))  | 
 | 94 |           dlsym(xp->dl_handle, PyString_AsString(name)); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 95 | 	if (func == NULL) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 96 | 		PyErr_SetString(PyExc_ValueError, dlerror()); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 97 | 		return NULL; | 
 | 98 | 	} | 
 | 99 | 	if (n-1 > 10) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 100 | 		PyErr_SetString(PyExc_TypeError, | 
 | 101 | 				"too many arguments (max 10)"); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 102 | 		return NULL; | 
 | 103 | 	} | 
 | 104 | 	for (i = 1; i < n; i++) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 105 | 		PyObject *v = PyTuple_GetItem(args, i); | 
 | 106 | 		if (PyInt_Check(v)) | 
 | 107 | 			alist[i-1] = PyInt_AsLong(v); | 
 | 108 | 		else if (PyString_Check(v)) | 
 | 109 | 			alist[i-1] = (long)PyString_AsString(v); | 
 | 110 | 		else if (v == Py_None) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 111 | 			alist[i-1] = (long) ((char *)NULL); | 
 | 112 | 		else { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 113 | 			PyErr_SetString(PyExc_TypeError, | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 114 | 				   "arguments must be int, string or None"); | 
 | 115 | 			return NULL; | 
 | 116 | 		} | 
 | 117 | 	} | 
 | 118 | 	for (; i <= 10; i++) | 
 | 119 | 		alist[i-1] = 0; | 
 | 120 | 	res = (*func)(alist[0], alist[1], alist[2], alist[3], alist[4], | 
 | 121 | 		      alist[5], alist[6], alist[7], alist[8], alist[9]); | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 122 | 	return PyInt_FromLong(res); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 123 | } | 
 | 124 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 125 | static PyMethodDef dlobject_methods[] = { | 
| Martin v. Löwis | 43b936d | 2002-01-17 23:15:58 +0000 | [diff] [blame] | 126 | 	{"call",	(PyCFunction)dl_call, METH_VARARGS}, | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 127 | 	{"sym", 	(PyCFunction)dl_sym, METH_O}, | 
 | 128 | 	{"close",	(PyCFunction)dl_close, METH_NOARGS}, | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 129 | 	{NULL,  	NULL}			 /* Sentinel */ | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 130 | }; | 
 | 131 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 132 | static PyObject * | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 133 | dl_getattr(dlobject *xp, char *name) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 134 | { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 135 | 	return Py_FindMethod(dlobject_methods, (PyObject *)xp, name); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 136 | } | 
 | 137 |  | 
 | 138 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 139 | static PyTypeObject Dltype = { | 
| Andrew M. Kuchling | 6efc6e7 | 2001-02-27 20:54:23 +0000 | [diff] [blame] | 140 | 	PyObject_HEAD_INIT(NULL) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 141 | 	0,			/*ob_size*/ | 
| Guido van Rossum | 1464839 | 2001-12-08 18:02:58 +0000 | [diff] [blame] | 142 | 	"dl.dl",		/*tp_name*/ | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 143 | 	sizeof(dlobject),	/*tp_basicsize*/ | 
 | 144 | 	0,			/*tp_itemsize*/ | 
 | 145 | 	/* methods */ | 
 | 146 | 	(destructor)dl_dealloc, /*tp_dealloc*/ | 
 | 147 | 	0,			/*tp_print*/ | 
 | 148 | 	(getattrfunc)dl_getattr,/*tp_getattr*/ | 
 | 149 | 	0,			/*tp_setattr*/ | 
 | 150 | 	0,			/*tp_compare*/ | 
 | 151 | 	0,			/*tp_repr*/ | 
 | 152 | 	0,			/*tp_as_number*/ | 
 | 153 | 	0,			/*tp_as_sequence*/ | 
 | 154 | 	0,			/*tp_as_mapping*/ | 
 | 155 | 	0,			/*tp_hash*/ | 
 | 156 | }; | 
 | 157 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 158 | static PyObject * | 
| Peter Schneider-Kamp | c4bc0e0 | 2000-07-10 11:56:03 +0000 | [diff] [blame] | 159 | dl_open(PyObject *self, PyObject *args) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 160 | { | 
 | 161 | 	char *name; | 
 | 162 | 	int mode; | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 163 | 	PyUnivPtr *handle; | 
| Martin v. Löwis | 9322727 | 2002-01-01 20:18:30 +0000 | [diff] [blame] | 164 | 	if (sizeof(int) != sizeof(long) || | 
 | 165 | 	    sizeof(long) != sizeof(char *)) { | 
 | 166 | 		PyErr_SetString(PyExc_SystemError, | 
 | 167 |  "module dl requires sizeof(int) == sizeof(long) == sizeof(char*)"); | 
 | 168 | 		return NULL; | 
 | 169 | 	} | 
 | 170 |  | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 171 | 	if (PyArg_ParseTuple(args, "z:open", &name)) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 172 | 		mode = RTLD_LAZY; | 
 | 173 | 	else { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 174 | 		PyErr_Clear(); | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 175 | 		if (!PyArg_ParseTuple(args, "zi:open", &name, &mode)) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 176 | 			return NULL; | 
 | 177 | #ifndef RTLD_NOW | 
 | 178 | 		if (mode != RTLD_LAZY) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 179 | 			PyErr_SetString(PyExc_ValueError, "mode must be 1"); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 180 | 			return NULL; | 
 | 181 | 		} | 
 | 182 | #endif | 
 | 183 | 	} | 
 | 184 | 	handle = dlopen(name, mode); | 
 | 185 | 	if (handle == NULL) { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 186 | 		PyErr_SetString(Dlerror, dlerror()); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 187 | 		return NULL; | 
 | 188 | 	} | 
 | 189 | 	return newdlobject(handle); | 
 | 190 | } | 
 | 191 |  | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 192 | static PyMethodDef dl_methods[] = { | 
| Neal Norwitz | b82d34f | 2002-03-31 15:43:28 +0000 | [diff] [blame] | 193 | 	{"open",	dl_open, METH_VARARGS}, | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 194 | 	{NULL,		NULL}		/* sentinel */ | 
 | 195 | }; | 
 | 196 |  | 
| Martin v. Löwis | df23f33 | 2000-09-13 16:26:10 +0000 | [diff] [blame] | 197 | /* From socketmodule.c | 
 | 198 |  * Convenience routine to export an integer value. | 
 | 199 |  * | 
 | 200 |  * Errors are silently ignored, for better or for worse... | 
 | 201 |  */ | 
 | 202 | static void | 
 | 203 | insint(PyObject *d, char *name, int value) | 
 | 204 | { | 
 | 205 | 	PyObject *v = PyInt_FromLong((long) value); | 
 | 206 | 	if (!v || PyDict_SetItemString(d, name, v)) | 
 | 207 | 		PyErr_Clear(); | 
 | 208 |  | 
 | 209 | 	Py_XDECREF(v); | 
 | 210 | } | 
 | 211 |  | 
| Mark Hammond | fe51c6d | 2002-08-02 02:27:13 +0000 | [diff] [blame] | 212 | PyMODINIT_FUNC | 
| Thomas Wouters | f3f33dc | 2000-07-21 06:00:07 +0000 | [diff] [blame] | 213 | initdl(void) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 214 | { | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 215 | 	PyObject *m, *d, *x; | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 216 |  | 
| Andrew M. Kuchling | 6efc6e7 | 2001-02-27 20:54:23 +0000 | [diff] [blame] | 217 | 	/* Initialize object type */ | 
 | 218 | 	Dltype.ob_type = &PyType_Type; | 
 | 219 |  | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 220 | 	/* Create the module and add the functions */ | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 221 | 	m = Py_InitModule("dl", dl_methods); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 222 |  | 
 | 223 | 	/* Add some symbolic constants to the module */ | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 224 | 	d = PyModule_GetDict(m); | 
| Guido van Rossum | 0cb96de | 1997-10-01 04:29:29 +0000 | [diff] [blame] | 225 | 	Dlerror = x = PyErr_NewException("dl.error", NULL, NULL); | 
| Roger E. Masse | 0e12032 | 1996-12-13 20:33:44 +0000 | [diff] [blame] | 226 | 	PyDict_SetItemString(d, "error", x); | 
 | 227 | 	x = PyInt_FromLong((long)RTLD_LAZY); | 
 | 228 | 	PyDict_SetItemString(d, "RTLD_LAZY", x); | 
| Martin v. Löwis | df23f33 | 2000-09-13 16:26:10 +0000 | [diff] [blame] | 229 | #define INSINT(X)    insint(d,#X,X) | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 230 | #ifdef RTLD_NOW | 
| Martin v. Löwis | df23f33 | 2000-09-13 16:26:10 +0000 | [diff] [blame] | 231 |         INSINT(RTLD_NOW); | 
 | 232 | #endif | 
 | 233 | #ifdef RTLD_NOLOAD | 
 | 234 |         INSINT(RTLD_NOLOAD); | 
 | 235 | #endif | 
 | 236 | #ifdef RTLD_GLOBAL | 
 | 237 |         INSINT(RTLD_GLOBAL); | 
 | 238 | #endif | 
 | 239 | #ifdef RTLD_LOCAL | 
 | 240 |         INSINT(RTLD_LOCAL); | 
 | 241 | #endif | 
 | 242 | #ifdef RTLD_PARENT | 
 | 243 |         INSINT(RTLD_PARENT); | 
 | 244 | #endif | 
 | 245 | #ifdef RTLD_GROUP | 
 | 246 |         INSINT(RTLD_GROUP); | 
 | 247 | #endif | 
 | 248 | #ifdef RTLD_WORLD | 
 | 249 |         INSINT(RTLD_WORLD); | 
 | 250 | #endif | 
 | 251 | #ifdef RTLD_NODELETE | 
 | 252 |         INSINT(RTLD_NODELETE); | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 253 | #endif | 
| Guido van Rossum | 34162a1 | 1994-05-23 12:37:57 +0000 | [diff] [blame] | 254 | } |