tclLoadDl.c

Go to the documentation of this file.
00001 /*
00002  * tclLoadDl.c --
00003  *
00004  *      This procedure provides a version of the TclLoadFile that works with
00005  *      the "dlopen" and "dlsym" library procedures for dynamic loading.
00006  *
00007  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
00008  *
00009  * See the file "license.terms" for information on usage and redistribution of
00010  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
00011  *
00012  * RCS: @(#) $Id: tclLoadDl.c,v 1.16 2006/06/13 22:10:19 dkf Exp $
00013  */
00014 
00015 #include "tclInt.h"
00016 #ifdef NO_DLFCN_H
00017 #   include "../compat/dlfcn.h"
00018 #else
00019 #   include <dlfcn.h>
00020 #endif
00021 
00022 /*
00023  * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined and this
00024  * argument to dlopen must always be 1. The RTLD_GLOBAL flag is needed on some
00025  * systems (e.g. SCO and UnixWare) but doesn't exist on others; if it doesn't
00026  * exist, set it to 0 so it has no effect.
00027  */
00028 
00029 #ifndef RTLD_NOW
00030 #   define RTLD_NOW 1
00031 #endif
00032 
00033 #ifndef RTLD_GLOBAL
00034 #   define RTLD_GLOBAL 0
00035 #endif
00036 
00037 /*
00038  *---------------------------------------------------------------------------
00039  *
00040  * TclpDlopen --
00041  *
00042  *      Dynamically loads a binary code file into memory and returns a handle
00043  *      to the new code.
00044  *
00045  * Results:
00046  *      A standard Tcl completion code. If an error occurs, an error message
00047  *      is left in the interp's result.
00048  *
00049  * Side effects:
00050  *      New code suddenly appears in memory.
00051  *
00052  *---------------------------------------------------------------------------
00053  */
00054 
00055 int
00056 TclpDlopen(
00057     Tcl_Interp *interp,         /* Used for error reporting. */
00058     Tcl_Obj *pathPtr,           /* Name of the file containing the desired
00059                                  * code (UTF-8). */
00060     Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
00061                                  * file which will be passed back to
00062                                  * (*unloadProcPtr)() to unload the file. */
00063     Tcl_FSUnloadFileProc **unloadProcPtr)
00064                                 /* Filled with address of Tcl_FSUnloadFileProc
00065                                  * function which should be used for this
00066                                  * file. */
00067 {
00068     void *handle;
00069     CONST char *native;
00070 
00071     /*
00072      * First try the full path the user gave us. This is particularly
00073      * important if the cwd is inside a vfs, and we are trying to load using a
00074      * relative path.
00075      */
00076 
00077     native = Tcl_FSGetNativePath(pathPtr);
00078     handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
00079     if (handle == NULL) {
00080         /*
00081          * Let the OS loader examine the binary search path for whatever
00082          * string the user gave us which hopefully refers to a file on the
00083          * binary path.
00084          */
00085 
00086         Tcl_DString ds;
00087         char *fileName = Tcl_GetString(pathPtr);
00088 
00089         native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
00090         handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
00091         Tcl_DStringFree(&ds);
00092     }
00093 
00094     if (handle == NULL) {
00095         /*
00096          * Write the string to a variable first to work around a compiler bug
00097          * in the Sun Forte 6 compiler. [Bug 1503729]
00098          */
00099 
00100         const char *errorStr = dlerror();
00101 
00102         Tcl_AppendResult(interp, "couldn't load file \"",
00103                 Tcl_GetString(pathPtr), "\": ", errorStr, NULL);
00104         return TCL_ERROR;
00105     }
00106 
00107     *unloadProcPtr = &TclpUnloadFile;
00108     *loadHandle = (Tcl_LoadHandle) handle;
00109     return TCL_OK;
00110 }
00111 
00112 /*
00113  *----------------------------------------------------------------------
00114  *
00115  * TclpFindSymbol --
00116  *
00117  *      Looks up a symbol, by name, through a handle associated with a
00118  *      previously loaded piece of code (shared library).
00119  *
00120  * Results:
00121  *      Returns a pointer to the function associated with 'symbol' if it is
00122  *      found. Otherwise returns NULL and may leave an error message in the
00123  *      interp's result.
00124  *
00125  *----------------------------------------------------------------------
00126  */
00127 
00128 Tcl_PackageInitProc *
00129 TclpFindSymbol(
00130     Tcl_Interp *interp,         /* Place to put error messages. */
00131     Tcl_LoadHandle loadHandle,  /* Value from TcpDlopen(). */
00132     CONST char *symbol)         /* Symbol to look up. */
00133 {
00134     CONST char *native;
00135     Tcl_DString newName, ds;
00136     VOID *handle = (VOID*)loadHandle;
00137     Tcl_PackageInitProc *proc;
00138 
00139     /*
00140      * Some platforms still add an underscore to the beginning of symbol
00141      * names. If we can't find a name without an underscore, try again with
00142      * the underscore.
00143      */
00144 
00145     native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
00146     proc = (Tcl_PackageInitProc *) dlsym(handle,        /* INTL: Native. */
00147             native);
00148     if (proc == NULL) {
00149         Tcl_DStringInit(&newName);
00150         Tcl_DStringAppend(&newName, "_", 1);
00151         native = Tcl_DStringAppend(&newName, native, -1);
00152         proc = (Tcl_PackageInitProc *) dlsym(handle,    /* INTL: Native. */
00153                 native);
00154         Tcl_DStringFree(&newName);
00155     }
00156     Tcl_DStringFree(&ds);
00157 
00158     return proc;
00159 }
00160 
00161 /*
00162  *----------------------------------------------------------------------
00163  *
00164  * TclpUnloadFile --
00165  *
00166  *      Unloads a dynamically loaded binary code file from memory. Code
00167  *      pointers in the formerly loaded file are no longer valid after calling
00168  *      this function.
00169  *
00170  * Results:
00171  *      None.
00172  *
00173  * Side effects:
00174  *      Code removed from memory.
00175  *
00176  *----------------------------------------------------------------------
00177  */
00178 
00179 void
00180 TclpUnloadFile(
00181     Tcl_LoadHandle loadHandle)  /* loadHandle returned by a previous call to
00182                                  * TclpDlopen(). The loadHandle is a token
00183                                  * that represents the loaded file. */
00184 {
00185     void *handle;
00186 
00187     handle = (void *) loadHandle;
00188     dlclose(handle);
00189 }
00190 
00191 /*
00192  *----------------------------------------------------------------------
00193  *
00194  * TclGuessPackageName --
00195  *
00196  *      If the "load" command is invoked without providing a package name,
00197  *      this procedure is invoked to try to figure it out.
00198  *
00199  * Results:
00200  *      Always returns 0 to indicate that we couldn't figure out a package
00201  *      name; generic code will then try to guess the package from the file
00202  *      name. A return value of 1 would have meant that we figured out the
00203  *      package name and put it in bufPtr.
00204  *
00205  * Side effects:
00206  *      None.
00207  *
00208  *----------------------------------------------------------------------
00209  */
00210 
00211 int
00212 TclGuessPackageName(
00213     CONST char *fileName,       /* Name of file containing package (already
00214                                  * translated to local form if needed). */
00215     Tcl_DString *bufPtr)        /* Initialized empty dstring. Append package
00216                                  * name to this if possible. */
00217 {
00218     return 0;
00219 }
00220 
00221 /*
00222  * Local Variables:
00223  * mode: c
00224  * c-basic-offset: 4
00225  * fill-column: 78
00226  * End:
00227  */



Generated on Wed Mar 12 12:18:25 2008 by  doxygen 1.5.1