It was possible to create a bad ref
[jimtcl.git] / jim-load.c
blobf853a5ead105e8ea1c57486d65ad4f14e7218fe8
1 #include <jim.h>
2 #include <string.h>
4 /* -----------------------------------------------------------------------------
5 * Dynamic libraries support (WIN32 not supported)
6 * ---------------------------------------------------------------------------*/
8 #ifdef JIM_DYNLIB
10 #include <dlfcn.h>
12 int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
14 Jim_Obj *libPathObjPtr;
15 int prefixc, i;
16 void *handle;
17 int (*onload) (Jim_Interp *interp);
19 libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE);
20 if (libPathObjPtr == NULL) {
21 prefixc = 0;
22 libPathObjPtr = NULL;
24 else {
25 Jim_IncrRefCount(libPathObjPtr);
26 prefixc = Jim_ListLength(interp, libPathObjPtr);
29 for (i = -1; i < prefixc; i++) {
30 if (i < 0) {
31 handle = dlopen(pathName, RTLD_LAZY);
33 else {
34 FILE *fp;
35 /* REVISIT: Move off stack */
36 char buf[JIM_PATH_LEN];
37 const char *prefix;
38 int prefixlen;
39 Jim_Obj *prefixObjPtr;
41 buf[0] = '\0';
42 if (Jim_ListIndex(interp, libPathObjPtr, i, &prefixObjPtr, JIM_NONE) != JIM_OK)
43 continue;
44 prefix = Jim_GetString(prefixObjPtr, &prefixlen);
45 if (prefixlen + strlen(pathName) + 1 >= JIM_PATH_LEN)
46 continue;
47 if (*pathName == '/') {
48 strcpy(buf, pathName);
50 else if (prefixlen && prefix[prefixlen - 1] == '/')
51 sprintf(buf, "%s%s", prefix, pathName);
52 else
53 sprintf(buf, "%s/%s", prefix, pathName);
54 fp = fopen(buf, "r");
55 if (fp == NULL)
56 continue;
57 fclose(fp);
58 handle = dlopen(buf, RTLD_LAZY);
60 if (handle == NULL) {
61 Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName,
62 dlerror());
63 if (i < 0)
64 continue;
65 goto err;
68 /* Now, we use a unique init symbol depending on the extension name.
69 * This is done for compatibility between static and dynamic extensions.
70 * For extension readline.so, the init symbol is "Jim_readlineInit"
73 const char *pt;
74 const char *pkgname;
75 int pkgnamelen;
76 char initsym[50];
78 pt = strrchr(pathName, '/');
79 if (pt) {
80 pkgname = pt + 1;
82 else {
83 pkgname = pathName;
85 pt = strchr(pkgname, '.');
86 if (pt) {
87 pkgnamelen = pt - pkgname;
89 else {
90 pkgnamelen = strlen(pkgname);
92 snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname);
94 if ((onload = dlsym(handle, initsym)) == NULL) {
95 Jim_SetResultFormatted(interp,
96 "No %s symbol found in extension %s", initsym, pathName);
97 goto err;
100 if (onload(interp) == JIM_ERR) {
101 dlclose(handle);
102 goto err;
104 Jim_SetEmptyResult(interp);
105 if (libPathObjPtr != NULL)
106 Jim_DecrRefCount(interp, libPathObjPtr);
107 return JIM_OK;
109 err:
110 if (libPathObjPtr != NULL)
111 Jim_DecrRefCount(interp, libPathObjPtr);
112 return JIM_ERR;
114 #else /* JIM_DYNLIB */
115 int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
117 JIM_NOTUSED(interp);
118 JIM_NOTUSED(pathName);
120 Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1);
121 return JIM_ERR;
123 #endif /* JIM_DYNLIB */
125 /* [load] */
126 static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
128 if (argc < 2) {
129 Jim_WrongNumArgs(interp, 1, argv, "libaryFile");
130 return JIM_ERR;
132 return Jim_LoadLibrary(interp, Jim_GetString(argv[1], NULL));
135 int Jim_loadInit(Jim_Interp *interp)
137 Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL);
138 return JIM_OK;