blob: 1f1ce462b1130d1f94033b05168cc627b76ee9b1 [file] [log] [blame]
Guido van Rossum34162a11994-05-23 12:37:57 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum34162a11994-05-23 12:37:57 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* dl module */
26
27#include "allobjects.h"
28#include "modsupport.h"
29
30#include <dlfcn.h>
31
32#ifndef RTLD_LAZY
33#define RTLD_LAZY 1
34#endif
35
36typedef struct {
37 OB_HEAD
38 ANY *dl_handle;
39} dlobject;
40
41staticforward typeobject Dltype;
42
43static object *Dlerror;
44
45static object *
46newdlobject(handle)
47 ANY *handle;
48{
49 dlobject *xp;
50 xp = NEWOBJ(dlobject, &Dltype);
51 if (xp == NULL)
52 return NULL;
53 xp->dl_handle = handle;
54 return (object *)xp;
55}
56
57static void
58dl_dealloc(xp)
59 dlobject *xp;
60{
61 if (xp->dl_handle != NULL)
62 dlclose(xp->dl_handle);
63 DEL(xp);
64}
65
66static object *
67dl_close(xp, args)
68 dlobject *xp;
69 object *args;
70{
71 if (!getargs(args, ""))
72 return NULL;
73 if (xp->dl_handle != NULL) {
74 dlclose(xp->dl_handle);
75 xp->dl_handle = NULL;
76 }
77 INCREF(None);
78 return None;
79}
80
81static object *
82dl_sym(xp, args)
83 dlobject *xp;
84 object *args;
85{
86 char *name;
87 ANY *func;
88 if (!getargs(args, "s", &name))
89 return NULL;
90 func = dlsym(xp->dl_handle, name);
91 if (func == NULL) {
92 INCREF(None);
93 return None;
94 }
95 return newintobject((long)func);
96}
97
98static object *
99dl_call(xp, args)
100 dlobject *xp;
101 object *args; /* (varargs) */
102{
103 object *name;
104 long (*func)();
105 long alist[10];
106 long res;
107 int i;
108 int n = gettuplesize(args);
109 if (n < 1) {
110 err_setstr(TypeError, "at least a name is needed");
111 return NULL;
112 }
113 name = gettupleitem(args, 0);
114 if (!is_stringobject(name)) {
115 err_setstr(TypeError, "function name must be a string");
116 return NULL;
117 }
118 func = dlsym(xp->dl_handle, getstringvalue(name));
119 if (func == NULL) {
120 err_setstr(ValueError, dlerror());
121 return NULL;
122 }
123 if (n-1 > 10) {
124 err_setstr(TypeError, "too many arguments (max 10)");
125 return NULL;
126 }
127 for (i = 1; i < n; i++) {
128 object *v = gettupleitem(args, i);
129 if (is_intobject(v))
130 alist[i-1] = getintvalue(v);
131 else if (is_stringobject(v))
132 alist[i-1] = (long)getstringvalue(v);
133 else if (v == None)
134 alist[i-1] = (long) ((char *)NULL);
135 else {
136 err_setstr(TypeError,
137 "arguments must be int, string or None");
138 return NULL;
139 }
140 }
141 for (; i <= 10; i++)
142 alist[i-1] = 0;
143 res = (*func)(alist[0], alist[1], alist[2], alist[3], alist[4],
144 alist[5], alist[6], alist[7], alist[8], alist[9]);
145 return newintobject(res);
146}
147
148static struct methodlist dlobject_methods[] = {
149 {"call", (method)dl_call, 1 /* varargs */},
150 {"sym", (method)dl_sym},
151 {"close", (method)dl_close},
152 {NULL, NULL} /* Sentinel */
153};
154
155static object *
156dl_getattr(xp, name)
157 dlobject *xp;
158 char *name;
159{
160 return findmethod(dlobject_methods, (object *)xp, name);
161}
162
163
164static typeobject Dltype = {
165 OB_HEAD_INIT(&Typetype)
166 0, /*ob_size*/
167 "dl", /*tp_name*/
168 sizeof(dlobject), /*tp_basicsize*/
169 0, /*tp_itemsize*/
170 /* methods */
171 (destructor)dl_dealloc, /*tp_dealloc*/
172 0, /*tp_print*/
173 (getattrfunc)dl_getattr,/*tp_getattr*/
174 0, /*tp_setattr*/
175 0, /*tp_compare*/
176 0, /*tp_repr*/
177 0, /*tp_as_number*/
178 0, /*tp_as_sequence*/
179 0, /*tp_as_mapping*/
180 0, /*tp_hash*/
181};
182
183static object *
184dl_open(self, args)
185 object *self;
186 object *args;
187{
188 char *name;
189 int mode;
190 ANY *handle;
191 if (getargs(args, "z", &name))
192 mode = RTLD_LAZY;
193 else {
194 err_clear();
195 if (!getargs(args, "(zi)", &name, &mode))
196 return NULL;
197#ifndef RTLD_NOW
198 if (mode != RTLD_LAZY) {
199 err_setstr(ValueError, "mode must be 1");
200 return NULL;
201 }
202#endif
203 }
204 handle = dlopen(name, mode);
205 if (handle == NULL) {
206 err_setstr(Dlerror, dlerror());
207 return NULL;
208 }
209 return newdlobject(handle);
210}
211
212static struct methodlist dl_methods[] = {
213 {"open", dl_open},
214 {NULL, NULL} /* sentinel */
215};
216
217void
218initdl()
219{
220 object *m, *d, *x;
221
222 if (sizeof(int) != sizeof(long) ||
223 sizeof(long) != sizeof(char *))
224 fatal(
225 "module dl requires sizeof(int) == sizeof(long) == sizeof(char*)");
226
227 /* Create the module and add the functions */
228 m = initmodule("dl", dl_methods);
229
230 /* Add some symbolic constants to the module */
231 d = getmoduledict(m);
232 Dlerror = x = newstringobject("dl.error");
233 dictinsert(d, "error", x);
234 x = newintobject((long)RTLD_LAZY);
235 dictinsert(d, "RTLD_LAZY", x);
236#ifdef RTLD_NOW
237 x = newintobject((long)RTLD_NOW);
238 dictinsert(d, "RTLD_NOW", x);
239#endif
240
241 /* Check for errors */
242 if (err_occurred())
243 fatal("can't initialize module dl");
244}