1/* 2 * load.c -- 3 * 4 * general purpose loader for shared libraries. 5 * essentially the last 2 functions of 'imgInit.c' 6 * (see 'Img' library by Jan Nijtmans). 7 * 8 * Copyright (c) 1996 Jan Nijtmans (nijtmans.nici.kun.nl) 9 * All rights reserved. 10 * 11 * CVS: $Id: load.c,v 1.5 1999/09/19 10:33:26 aku Exp $ 12 */ 13 14#include "transformInt.h" 15 16#define Offset(type,field) ((unsigned long) (((char *) &((type *) 0)->field))) 17 18/* 19 *---------------------------------------------------------------------- 20 * 21 * Trf_LoadLibrary -- 22 * 23 * This procedure is called to load a shared library into memory. 24 * If the extension is ".so" (e.g. Solaris, Linux) or ".sl" (HP-UX) 25 * it is possible that the extension is appended or replaced with 26 * a major version number. If the file cannot be found, the version 27 * numbers will be stripped off one by one. e.g. 28 * 29 * HP-UX: libtiff.3.4 Linux,Solaris: libtiff.so.3.4 30 * libtiff.3 libtiff.so.3 31 * libtiff.sl libtiff.so 32 * 33 * Results: 34 * TCL_OK if function succeeds. Otherwise TCL_ERROR while the 35 * interpreter will contain an error-message. The last parameter 36 * "num" contains the minimum number of symbols that is required 37 * by the application to succeed. Only the first <num> symbols 38 * will produce an error if they cannot be found. 39 * 40 * Side effects: 41 * At least <num> Library functions become available by the 42 * application. 43 * 44 *---------------------------------------------------------------------- 45 */ 46 47typedef struct Functions { 48 VOID *handle; 49 int (* first) _ANSI_ARGS_((void)); 50 int (* next) _ANSI_ARGS_((void)); 51} Functions; 52 53/* MS defines something under this name, avoid the collision 54 */ 55 56#define TRF_LOAD_FAILED ((VOID *) -114) 57 58int 59Trf_LoadLibrary (interp, libName, handlePtr, symbols, num) 60 Tcl_Interp *interp; 61 CONST char *libName; 62 VOID **handlePtr; 63 char **symbols; 64 int num; 65{ 66 VOID *handle = (VOID *) NULL; 67 Functions *lib = (Functions *) handlePtr; 68 char **p = (char **) &(lib->first); 69 char **q = symbols; 70 char buf[256]; 71 char *r; 72 int length; 73 74 if (lib->handle != NULL) { 75 if (lib->handle == TRF_LOAD_FAILED) { 76 Tcl_AppendResult (interp, "cannot open ", (char*) NULL); 77 Tcl_AppendResult (interp, libName, (char*) NULL); 78 } 79 return (lib->handle != TRF_LOAD_FAILED) ? TCL_OK : TCL_ERROR; 80 } 81 82 length = strlen(libName); 83 strcpy(buf,libName); 84 handle = dlopen(buf, RTLD_NOW); 85 86 while (handle == NULL) { 87 if ((r = strrchr(buf,'.')) != NULL) { 88 if ((r[1] < '0') || (r[1] > '9')) { 89 Tcl_AppendResult (interp, "cannot open ", (char*) NULL); 90 Tcl_AppendResult (interp, libName, (char*) NULL); 91 Tcl_AppendResult (interp, ": ", (char*) NULL); 92 Tcl_AppendResult (interp, dlerror (), (char*) NULL); 93 lib->handle = TRF_LOAD_FAILED; 94 return TCL_ERROR; 95 } 96 length = r - buf; 97 *r = 0; 98 } 99 if (strchr(buf,'.') == NULL) { 100 strcpy(buf+length,".sl"); 101 length += 3; 102 } 103 dlerror(); 104 handle = dlopen(buf, RTLD_NOW); 105 } 106 107 buf[0] = '_'; 108 while (*q) { 109 *p = (char *) dlsym(handle,*q); 110 if (*p == (char *)NULL) { 111 strcpy(buf+1,*q); 112 *p = (char *) dlsym(handle,buf); 113 if ((num > 0) && (*p == (char *)NULL)) { 114 Tcl_AppendResult (interp, "cannot open ", (char*) NULL); 115 Tcl_AppendResult (interp, libName, (char*) NULL); 116 Tcl_AppendResult (interp, ": symbol \"", (char*) NULL); 117 Tcl_AppendResult (interp, *q, (char*) NULL); 118 Tcl_AppendResult (interp, "\" not found", (char*) NULL); 119 dlclose(handle); 120 lib->handle = TRF_LOAD_FAILED; 121 return TCL_ERROR; 122 } 123 } 124 q++; num--; 125 p += (Offset(Functions, next) - Offset(Functions, first)) / 126 sizeof(char *); 127 } 128 lib->handle = handle; 129 130 return TCL_OK; 131} 132 133/* 134 *---------------------------------------------------------------------- 135 * 136 * Trf_LoadFailed -- 137 * 138 * Mark the loaded library as invalid. Remove it from memory 139 * if possible. It will no longer be used in the future. 140 * 141 * Results: 142 * None. 143 * 144 * Side effects: 145 * Next time the same handle is used by TrfLoadLib, it will 146 * fail immediately, without trying to load it. 147 * 148 *---------------------------------------------------------------------- 149 */ 150 151void 152Trf_LoadFailed (handlePtr) 153 VOID **handlePtr; 154{ 155 if ((*handlePtr != NULL) && (*handlePtr != TRF_LOAD_FAILED)) { 156 /* Oops, still loaded. First remove it from menory */ 157 dlclose(*handlePtr); 158 } 159 *handlePtr = TRF_LOAD_FAILED; 160} 161