ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/dynlink.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (19 years, 10 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/dynlink.c
File size: 10077 byte(s)
Log Message:
- svn:keywords

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * dynlink.c: A module loader.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 *
24     */
25     #include "stdinc.h"
26     #include "tools.h"
27     #include "irc_string.h"
28     #include "modules.h"
29     #include "s_log.h"
30     #include "client.h"
31     #include "send.h"
32    
33     #ifndef RTLD_NOW
34     #define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
35     #endif
36    
37     extern dlink_list mod_list;
38    
39     static char unknown_ver[] = "<unknown>";
40    
41     /* This file contains the core functions to use dynamic libraries.
42     * -TimeMr14C
43     */
44    
45     #if !defined(HAVE_SHL_LOAD) && !defined(HAVE_DLFUNC)
46     /*
47     * Fake dlfunc(3) if we don't have it, cause it's happy.
48     */
49     typedef void (*__function_p)(void);
50    
51     static __function_p
52     dlfunc(void *myHandle, const char *functionName)
53     {
54     /* XXX This is not guaranteed to work, but with
55     * traditional dl*(3), it is the best we can do.
56     * -jmallett
57     */
58     void *symbolp;
59    
60     symbolp = dlsym(myHandle, functionName);
61     return((__function_p)(uintptr_t)symbolp);
62     }
63     #endif
64    
65     #ifdef HAVE_MACH_O_DYLD_H
66     /*
67     ** jmallett's dl*(3) shims for NSModule(3) systems.
68     */
69     #include <mach-o/dyld.h>
70    
71     #ifndef HAVE_DLOPEN
72     #ifndef RTLD_LAZY
73     #define RTLD_LAZY 2185 /* built-in dl*(3) don't care */
74     #endif
75    
76     void undefinedErrorHandler(const char *);
77     NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
78     void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
79     char *dlerror(void);
80     void *dlopen(char *, int);
81     int dlclose(void *);
82     void *dlsym(void *, char *);
83    
84     static int firstLoad = TRUE;
85     static int myDlError;
86     static const char *myErrorTable[] =
87     {
88     "Loading file as object failed\n",
89     "Loading file as object succeeded\n",
90     "Not a valid shared object\n",
91     "Architecture of object invalid on this architecture\n",
92     "Invalid or corrupt image\n",
93     "Could not access object\n",
94     "NSCreateObjectFileImageFromFile failed\n",
95     NULL
96     };
97    
98     void
99     undefinedErrorHandler(const char *symbolName)
100     {
101     sendto_realops_flags(UMODE_ALL, L_ALL, "Undefined symbol: %s", symbolName);
102     ilog(L_WARN, "Undefined symbol: %s", symbolName);
103     return;
104     }
105    
106     NSModule
107     multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
108     {
109     /* XXX
110     ** This results in substantial leaking of memory... Should free one
111     ** module, maybe?
112     */
113     sendto_realops_flags(UMODE_ALL, L_ALL, "Symbol `%s' found in `%s' and `%s'",
114     NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
115     ilog(L_WARN, "Symbol `%s' found in `%s' and `%s'", NSNameOfSymbol(s),
116     NSNameOfModule(old), NSNameOfModule(new));
117     /* We return which module should be considered valid, I believe */
118     return(new);
119     }
120    
121     void
122     linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
123     const char *fileName, const char *errorString)
124     {
125     sendto_realops_flags(UMODE_ALL, L_ALL, "Link editor error: %s for %s",
126     errorString, fileName);
127     ilog(L_WARN, "Link editor error: %s for %s", errorString, fileName);
128     return;
129     }
130    
131     char *
132     dlerror(void)
133     {
134     return(myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7]);
135     }
136    
137     void *
138     dlopen(char *filename, int unused)
139     {
140     NSObjectFileImage myImage;
141     NSModule myModule;
142    
143     if (firstLoad)
144     {
145     /* If we are loading our first symbol (huzzah!) we should go ahead
146     * and install link editor error handling!
147     */
148     NSLinkEditErrorHandlers linkEditorErrorHandlers;
149    
150     linkEditorErrorHandlers.undefined = undefinedErrorHandler;
151     linkEditorErrorHandlers.multiple = multipleErrorHandler;
152     linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
153     NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
154     firstLoad = FALSE;
155     }
156    
157     myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
158    
159     if (myDlError != NSObjectFileImageSuccess)
160     return(NULL);
161    
162     myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
163     return((void *)myModule);
164     }
165    
166     int
167     dlclose(void *myModule)
168     {
169     NSUnLinkModule(myModule, FALSE);
170     return(0);
171     }
172    
173     void *
174     dlsym(void *myModule, char *mySymbolName)
175     {
176     NSSymbol mySymbol;
177    
178     mySymbol = NSLookupSymbolInModule((NSModule)myModule, mySymbolName);
179     return NSAddressOfSymbol(mySymbol);
180     }
181     #endif
182     #endif
183    
184     /* unload_one_module()
185     *
186     * inputs - name of module to unload
187     * - 1 to say modules unloaded, 0 to not
188     * output - 0 if successful, -1 if error
189     * side effects - module is unloaded
190     */
191     int
192     unload_one_module(char *name, int warn)
193     {
194     dlink_node *ptr = NULL;
195     struct module *modp = NULL;
196    
197     if ((ptr = findmodule_byname(name)) == NULL)
198     return -1;
199    
200     modp = ptr->data;
201    
202     if (modp->modremove)
203     (*modp->modremove)();
204    
205     #ifdef HAVE_SHL_LOAD
206     /* shl_* and friends have a slightly different format than dl*. But it does not
207     * require creation of a totally new modules.c, instead proper usage of
208     * defines solve this case. -TimeMr14C
209     */
210     shl_unload((shl_t) & (modp->address));
211     #else
212     /* We use FreeBSD's dlfunc(3) interface, or fake it as we
213     * used to here if it isn't there. The interface should
214     * be standardised some day, and so it eventually will be
215     * providing something guaranteed to do the right thing here.
216     * -jmallett
217     */
218     dlclose(modp->address);
219     #endif
220     assert(dlink_list_length(&mod_list) > 0);
221     dlinkDelete(ptr, &mod_list);
222     MyFree(modp->name);
223     MyFree(modp);
224    
225     if (warn == 1)
226     {
227     ilog(L_INFO, "Module %s unloaded", name);
228     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s unloaded", name);
229     }
230    
231     return 0;
232     }
233    
234     /* load_a_module()
235     *
236     * inputs - path name of module, int to notice, int of core
237     * output - -1 if error 0 if success
238     * side effects - loads a module if successful
239     */
240     int
241     load_a_module(char *path, int warn, int core)
242     {
243     #ifdef HAVE_SHL_LOAD
244     shl_t tmpptr;
245     #else
246     void *tmpptr = NULL;
247     #endif
248     char *mod_basename;
249     void (*initfunc)(void) = NULL;
250     void (*mod_deinit)(void) = NULL;
251     char **verp;
252     char *ver;
253     struct module *modp;
254    
255     mod_basename = basename(path);
256    
257     if (findmodule_byname(mod_basename) != NULL)
258     return(1);
259    
260     #ifdef HAVE_SHL_LOAD
261     tmpptr = shl_load(path, BIND_IMMEDIATE, NULL);
262     #else
263     tmpptr = dlopen(path, RTLD_NOW);
264     #endif
265    
266     if (tmpptr == NULL)
267     {
268     #ifdef HAVE_SHL_LOAD
269     const char *err = strerror(errno);
270     #else
271     const char *err = dlerror();
272     #endif
273     sendto_realops_flags(UMODE_ALL, L_ALL, "Error loading module %s: %s",
274     mod_basename, err);
275     ilog(L_WARN, "Error loading module %s: %s", mod_basename, err);
276    
277     return(-1);
278     }
279    
280     #ifdef HAVE_SHL_LOAD
281     if (shl_findsym(&tmpptr, "_modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
282     {
283     if (shl_findsym(&tmpptr, "__modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
284     {
285     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
286     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
287     mod_basename);
288     shl_unload(tmpptr);
289     return(-1);
290     }
291     }
292    
293     if (shl_findsym(&tmpptr, "_moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
294     {
295     if (shl_findsym(&tmpptr, "__moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
296     {
297     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
298     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
299     mod_basename);
300     /* this is a soft error. we're allowed not to have one, i guess.
301     * (judging by the code in unload_one_module() */
302     mod_deinit = NULL;
303     }
304     }
305    
306     if (shl_findsym(&tmpptr, "_version", TYPE_UNDEFINED, &verp) == -1)
307     {
308     if (shl_findsym(&tmpptr, "__version", TYPE_UNDEFINED, &verp) == -1)
309     ver = unknown_ver;
310     else
311     ver = *verp;
312     }
313     else
314     ver = *verp;
315     #else
316     if ((initfunc = (void(*)(void))dlfunc(tmpptr, "_modinit")) == NULL &&
317     /* Only for compatibility, because some systems have underscore
318     * prepended symbol names */
319     (initfunc = (void(*)(void))dlfunc(tmpptr, "__modinit")) == NULL)
320     {
321     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
322     mod_basename);
323     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
324     dlclose(tmpptr);
325     return(-1);
326     }
327    
328     mod_deinit = (void(*)(void))dlfunc(tmpptr, "_moddeinit");
329    
330     if (mod_deinit == NULL && (mod_deinit = (void(*)(void))dlfunc(tmpptr, "__moddeinit")) == NULL)
331     {
332     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
333     mod_basename);
334     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
335     /* blah blah soft error, see above. */
336     mod_deinit = NULL;
337     }
338    
339     verp = (char **)dlsym(tmpptr, "_version");
340    
341     if (verp == NULL && (verp = (char **)dlsym(tmpptr, "__version")) == NULL)
342     ver = unknown_ver;
343     else
344     ver = *verp;
345     #endif
346    
347     modp = MyMalloc(sizeof(struct module));
348     modp->address = tmpptr;
349     modp->version = ver;
350     modp->core = core;
351     modp->modremove = mod_deinit;
352    
353     DupString(modp->name, mod_basename);
354     dlinkAdd(modp, &modp->node, &mod_list);
355    
356     initfunc();
357    
358     if (warn == 1)
359     {
360     sendto_realops_flags(UMODE_ALL, L_ALL,
361     "Module %s [version: %s] loaded at %p",
362     mod_basename, ver, tmpptr);
363     ilog(L_WARN, "Module %s [version: %s] loaded at %p",
364     mod_basename, ver, tmpptr);
365     }
366    
367     return(0);
368     }

Properties

Name Value
svn:eol-style native
svn:keywords Revision