1#include "jim.h" 2#include "jimautoconf.h" 3#include <string.h> 4 5/* ----------------------------------------------------------------------------- 6 * Dynamic libraries support (WIN32 not supported) 7 * ---------------------------------------------------------------------------*/ 8 9#if defined(HAVE_DLOPEN) || defined(HAVE_DLOPEN_COMPAT) 10 11#ifdef HAVE_DLFCN_H 12#include <dlfcn.h> 13#endif 14 15#ifndef RTLD_NOW 16 #define RTLD_NOW 0 17#endif 18#ifndef RTLD_LOCAL 19 #define RTLD_LOCAL 0 20#endif 21 22/** 23 * Note that Jim_LoadLibrary() requires a path to an existing file. 24 * 25 * If it is necessary to search JIM_LIBPATH, use Jim_PackageRequire() instead. 26 */ 27int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) 28{ 29 void *handle = dlopen(pathName, RTLD_NOW | RTLD_LOCAL); 30 if (handle == NULL) { 31 Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName, 32 dlerror()); 33 } 34 else { 35 /* We use a unique init symbol depending on the extension name. 36 * This is done for compatibility between static and dynamic extensions. 37 * For extension readline.so, the init symbol is "Jim_readlineInit" 38 */ 39 const char *pt; 40 const char *pkgname; 41 int pkgnamelen; 42 char initsym[40]; 43 int (*onload) (Jim_Interp *); 44 45 pt = strrchr(pathName, '/'); 46 if (pt) { 47 pkgname = pt + 1; 48 } 49 else { 50 pkgname = pathName; 51 } 52 pt = strchr(pkgname, '.'); 53 if (pt) { 54 pkgnamelen = pt - pkgname; 55 } 56 else { 57 pkgnamelen = strlen(pkgname); 58 } 59 snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname); 60 61 if ((onload = dlsym(handle, initsym)) == NULL) { 62 Jim_SetResultFormatted(interp, 63 "No %s symbol found in extension %s", initsym, pathName); 64 } 65 else if (onload(interp) != JIM_ERR) { 66 /* Add this handle to the stack of handles to be freed */ 67 if (!interp->loadHandles) { 68 interp->loadHandles = Jim_Alloc(sizeof(*interp->loadHandles)); 69 Jim_InitStack(interp->loadHandles); 70 } 71 Jim_StackPush(interp->loadHandles, handle); 72 73 Jim_SetEmptyResult(interp); 74 75 return JIM_OK; 76 } 77 } 78 if (handle) { 79 dlclose(handle); 80 } 81 return JIM_ERR; 82} 83 84static void JimFreeOneLoadHandle(void *handle) 85{ 86 dlclose(handle); 87} 88 89void Jim_FreeLoadHandles(Jim_Interp *interp) 90{ 91 if (interp->loadHandles) { 92 Jim_FreeStackElements(interp->loadHandles, JimFreeOneLoadHandle); 93 Jim_Free(interp->loadHandles); 94 } 95} 96 97#else /* JIM_DYNLIB */ 98int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) 99{ 100 JIM_NOTUSED(interp); 101 JIM_NOTUSED(pathName); 102 103 Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1); 104 return JIM_ERR; 105} 106 107void Jim_FreeLoadHandles(Jim_Interp *interp) 108{ 109} 110#endif /* JIM_DYNLIB */ 111 112/* [load] */ 113static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 114{ 115 if (argc < 2) { 116 Jim_WrongNumArgs(interp, 1, argv, "libaryFile"); 117 return JIM_ERR; 118 } 119 return Jim_LoadLibrary(interp, Jim_String(argv[1])); 120} 121 122int Jim_loadInit(Jim_Interp *interp) 123{ 124 Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL); 125 return JIM_OK; 126} 127