00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdinc.h"
00026 #include "tools.h"
00027 #include "irc_string.h"
00028 #include "modules.h"
00029 #include "s_log.h"
00030 #include "client.h"
00031 #include "send.h"
00032
00033 #ifndef RTLD_NOW
00034 #define RTLD_NOW RTLD_LAZY
00035 #endif
00036
00037 #if defined(HAVE_DLINFO) && defined(HAVE_LINK_H)
00038 # include <link.h>
00039 #endif
00040
00041 extern dlink_list mod_list;
00042
00043 static char unknown_ver[] = "<unknown>";
00044
00045
00046
00047
00048
00049 #if !defined(HAVE_SHL_LOAD) && !defined(HAVE_DLFUNC)
00050
00051
00052
00053 typedef void (*__function_p)(void);
00054
00055 static __function_p
00056 dlfunc(void *myHandle, const char *functionName)
00057 {
00058
00059
00060
00061
00062 void *symbolp;
00063
00064 symbolp = dlsym(myHandle, functionName);
00065 return((__function_p)(uintptr_t)symbolp);
00066 }
00067 #endif
00068
00069 #ifdef HAVE_MACH_O_DYLD_H
00070
00071
00072
00073 #include <mach-o/dyld.h>
00074
00075 #ifndef HAVE_DLOPEN
00076 #ifndef RTLD_LAZY
00077 #define RTLD_LAZY 2185
00078 #endif
00079
00080 void undefinedErrorHandler(const char *);
00081 NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
00082 void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
00083 char *dlerror(void);
00084 void *dlopen(char *, int);
00085 int dlclose(void *);
00086 void *dlsym(void *, char *);
00087
00088 static int firstLoad = TRUE;
00089 static int myDlError;
00090 static const char *myErrorTable[] =
00091 {
00092 "Loading file as object failed\n",
00093 "Loading file as object succeeded\n",
00094 "Not a valid shared object\n",
00095 "Architecture of object invalid on this architecture\n",
00096 "Invalid or corrupt image\n",
00097 "Could not access object\n",
00098 "NSCreateObjectFileImageFromFile failed\n",
00099 NULL
00100 };
00101
00102 void
00103 undefinedErrorHandler(const char *symbolName)
00104 {
00105 sendto_realops_flags(UMODE_ALL, L_ALL, "Undefined symbol: %s", symbolName);
00106 ilog(L_WARN, "Undefined symbol: %s", symbolName);
00107 return;
00108 }
00109
00110 NSModule
00111 multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
00112 {
00113
00114
00115
00116
00117 sendto_realops_flags(UMODE_ALL, L_ALL, "Symbol `%s' found in `%s' and `%s'",
00118 NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
00119 ilog(L_WARN, "Symbol `%s' found in `%s' and `%s'", NSNameOfSymbol(s),
00120 NSNameOfModule(old), NSNameOfModule(new));
00121
00122 return(new);
00123 }
00124
00125 void
00126 linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
00127 const char *fileName, const char *errorString)
00128 {
00129 sendto_realops_flags(UMODE_ALL, L_ALL, "Link editor error: %s for %s",
00130 errorString, fileName);
00131 ilog(L_WARN, "Link editor error: %s for %s", errorString, fileName);
00132 return;
00133 }
00134
00135 char *
00136 dlerror(void)
00137 {
00138 return(myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7]);
00139 }
00140
00141 void *
00142 dlopen(char *filename, int unused)
00143 {
00144 NSObjectFileImage myImage;
00145 NSModule myModule;
00146
00147 if (firstLoad)
00148 {
00149
00150
00151
00152 NSLinkEditErrorHandlers linkEditorErrorHandlers;
00153
00154 linkEditorErrorHandlers.undefined = undefinedErrorHandler;
00155 linkEditorErrorHandlers.multiple = multipleErrorHandler;
00156 linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
00157 NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
00158 firstLoad = FALSE;
00159 }
00160
00161 myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
00162
00163 if (myDlError != NSObjectFileImageSuccess)
00164 return(NULL);
00165
00166 myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
00167 return((void *)myModule);
00168 }
00169
00170 int
00171 dlclose(void *myModule)
00172 {
00173 NSUnLinkModule(myModule, FALSE);
00174 return(0);
00175 }
00176
00177 void *
00178 dlsym(void *myModule, char *mySymbolName)
00179 {
00180 NSSymbol mySymbol;
00181
00182 mySymbol = NSLookupSymbolInModule((NSModule)myModule, mySymbolName);
00183 return NSAddressOfSymbol(mySymbol);
00184 }
00185 #endif
00186 #endif
00187
00188
00189
00190
00191
00192
00193
00194
00195 int
00196 unload_one_module(char *name, int warn)
00197 {
00198 dlink_node *ptr = NULL;
00199 struct module *modp = NULL;
00200
00201 if ((ptr = findmodule_byname(name)) == NULL)
00202 return -1;
00203
00204 modp = ptr->data;
00205
00206 if (modp->modremove)
00207 (*modp->modremove)();
00208
00209 #ifdef HAVE_SHL_LOAD
00210
00211
00212
00213
00214 shl_unload((shl_t) & (modp->handle));
00215 #else
00216
00217
00218
00219
00220
00221
00222 dlclose(modp->handle);
00223 #endif
00224 assert(dlink_list_length(&mod_list) > 0);
00225 dlinkDelete(ptr, &mod_list);
00226 MyFree(modp->name);
00227 MyFree(modp);
00228
00229 if (warn == 1)
00230 {
00231 ilog(L_INFO, "Module %s unloaded", name);
00232 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s unloaded", name);
00233 }
00234
00235 return 0;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 int
00245 load_a_module(char *path, int warn, int core)
00246 {
00247 #ifdef HAVE_DLINFO
00248 struct link_map *map;
00249 #endif
00250 #ifdef HAVE_SHL_LOAD
00251 shl_t tmpptr;
00252 #else
00253 void *tmpptr = NULL;
00254 #endif
00255 void *addr = NULL;
00256 char *mod_basename;
00257 void (*initfunc)(void) = NULL;
00258 void (*mod_deinit)(void) = NULL;
00259 char **verp;
00260 char *ver;
00261 struct module *modp;
00262
00263 mod_basename = basename(path);
00264
00265 if (findmodule_byname(mod_basename) != NULL)
00266 return(1);
00267
00268 #ifdef HAVE_SHL_LOAD
00269 tmpptr = shl_load(path, BIND_IMMEDIATE, NULL);
00270 #else
00271 tmpptr = dlopen(path, RTLD_NOW);
00272 #endif
00273
00274 if (tmpptr == NULL)
00275 {
00276 #ifdef HAVE_SHL_LOAD
00277 const char *err = strerror(errno);
00278 #else
00279 const char *err = dlerror();
00280 #endif
00281 sendto_realops_flags(UMODE_ALL, L_ALL, "Error loading module %s: %s",
00282 mod_basename, err);
00283 ilog(L_WARN, "Error loading module %s: %s", mod_basename, err);
00284
00285 return(-1);
00286 }
00287
00288 #ifdef HAVE_SHL_LOAD
00289 if (shl_findsym(&tmpptr, "_modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
00290 {
00291 if (shl_findsym(&tmpptr, "__modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
00292 {
00293 ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
00294 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
00295 mod_basename);
00296 shl_unload(tmpptr);
00297 return(-1);
00298 }
00299 }
00300
00301 if (shl_findsym(&tmpptr, "_moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
00302 {
00303 if (shl_findsym(&tmpptr, "__moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
00304 {
00305 ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
00306 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
00307 mod_basename);
00308
00309
00310 mod_deinit = NULL;
00311 }
00312 }
00313
00314 if (shl_findsym(&tmpptr, "_version", TYPE_UNDEFINED, &verp) == -1)
00315 {
00316 if (shl_findsym(&tmpptr, "__version", TYPE_UNDEFINED, &verp) == -1)
00317 ver = unknown_ver;
00318 else
00319 ver = *verp;
00320 }
00321 else
00322 ver = *verp;
00323 #else
00324 if ((initfunc = (void(*)(void))dlfunc(tmpptr, "_modinit")) == NULL &&
00325
00326
00327 (initfunc = (void(*)(void))dlfunc(tmpptr, "__modinit")) == NULL)
00328 {
00329 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
00330 mod_basename);
00331 ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
00332 dlclose(tmpptr);
00333 return(-1);
00334 }
00335
00336 mod_deinit = (void(*)(void))dlfunc(tmpptr, "_moddeinit");
00337
00338 if (mod_deinit == NULL && (mod_deinit = (void(*)(void))dlfunc(tmpptr, "__moddeinit")) == NULL)
00339 {
00340 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
00341 mod_basename);
00342 ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
00343
00344 mod_deinit = NULL;
00345 }
00346
00347 verp = (char **)dlsym(tmpptr, "_version");
00348
00349 if (verp == NULL && (verp = (char **)dlsym(tmpptr, "__version")) == NULL)
00350 ver = unknown_ver;
00351 else
00352 ver = *verp;
00353 #endif
00354
00355 modp = MyMalloc(sizeof(struct module));
00356 #ifdef HAVE_DLINFO
00357 dlinfo(tmpptr, RTLD_DI_LINKMAP, &map);
00358 if (map != NULL)
00359 addr = (void *)map->l_addr;
00360 else
00361 #endif
00362 addr = tmpptr;
00363
00364 modp->handle = tmpptr;
00365 modp->address = addr;
00366 modp->version = ver;
00367 modp->core = core;
00368 modp->modremove = mod_deinit;
00369
00370 DupString(modp->name, mod_basename);
00371 dlinkAdd(modp, &modp->node, &mod_list);
00372
00373 initfunc();
00374
00375 if (warn == 1)
00376 {
00377 sendto_realops_flags(UMODE_ALL, L_ALL,
00378 "Module %s [version: %s] loaded at %p",
00379 mod_basename, ver, addr);
00380 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
00381 mod_basename, ver, addr);
00382 }
00383
00384 return(0);
00385 }