⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynload.c

📁 Serveez是一个服务器框架
💻 C
字号:
/* * dynload.c - dynamic server loading implementation * * Copyright (C) 2001 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. *  * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: dynload.c,v 1.18 2001/10/03 14:42:43 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#if HAVE_DL_H# include <dl.h>#endif#ifdef __BEOS__# include <kernel/image.h>#endif#if HAVE_DLD_H# include <dld.h>#endif#if HAVE_DLFCN_H# include <dlfcn.h># ifndef RTLD_GLOBAL#  define RTLD_GLOBAL 0# endif#endif#if HAVE_MACH_O_DYLD_H#include <mach-o/dyld.h>#endif#ifdef __MINGW32__# include <winsock2.h>#endif#include "libserveez/alloc.h"#include "libserveez/util.h"#include "libserveez/socket.h"#include "libserveez/server.h"#include "libserveez/dynload.h"/* Internal list of shared libraries. */static int dyn_libraries = 0;static dyn_library_t *dyn_library = NULL;/* Print the current shared library error description. */#if HAVE_DLOPEN# define dyn_error() dlerror ()#elif HAVE_NSADDIMAGEstatic char * dyn_error (void){  NSLinkEditErrors errors;  int n;  const char *file, *err;  NSLinkEditError (&errors, &n, &file, &err);  return (char *) err;}#else# define dyn_error() SYS_ERROR#endif/* Define library prefix and suffix. */#if defined (__MINGW32__) || defined (__CYGWIN__)# if defined (__CYGWIN__)#  define DYNLOAD_PREFIX "cyg"# else#  define DYNLOAD_PREFIX "lib"# endif# define DYNLOAD_SUFFIX "dll"# define DYNLOAD_PATH_SEPERATOR ';'# define DYNLOAD_SYMBOL_PREFIX ""#elif defined (HAVE_NSADDIMAGE)# define DYNLOAD_PREFIX "lib"# define DYNLOAD_SUFFIX "dylib"# define DYNLOAD_PATH_SEPERATOR ':'# define DYNLOAD_SYMBOL_PREFIX "_"#else# define DYNLOAD_PREFIX "lib"# define DYNLOAD_SUFFIX "so"# define DYNLOAD_PATH_SEPERATOR ':'# define DYNLOAD_SYMBOL_PREFIX ""#endif/* Name of the additional search path environment variable. */#define DYNLOAD_PATH "SERVEEZ_LOAD_PATH"/* * Find a library handle for a given library's name @var{file} in the current * list of loaded shared libraries. Return @code{NULL} if there is no such  * thing. */static dyn_library_t *dyn_find_library (char *file){  int n;  /* go through all loaded libraries and check if there is such a */  for (n = 0; n < dyn_libraries; n++)    if (!strcmp (dyn_library[n].file, file))      return &dyn_library[n];  return NULL;}/* * This functions tries to link a library called @var{file} and returns * its handle or NULL if it failed. If the argument @var{path} is given * it prepends this to the file name of the library. */static void *dyn_get_library (char *path, char *file){  void *handle = NULL;  char *lib;  lib = svz_malloc ((path ? strlen (path) + 1 : 0) + strlen (file) + 1);  sprintf (lib, "%s%s%s", path ? path : "", path ? "/" : "", file);#if HAVE_DLOPEN  handle = dlopen (lib, RTLD_NOW | RTLD_GLOBAL);#elif defined (__BEOS__)  handle = load_add_on (lib);  if ((image_id) handle <= 0)    handle = NULL;#elif HAVE_DLD_LINK  handle = dld_link (lib);#elif defined (__MINGW32__)  handle = LoadLibrary (lib);#elif HAVE_SHL_LOAD  handle = shl_load (lib, BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH);#elif HAVE_NSADDIMAGE  handle = (void *) NSAddImage (lib, NSADDIMAGE_OPTION_RETURN_ON_ERROR |				NSADDIMAGE_OPTION_WITH_SEARCHING);#endif  svz_free (lib);  return handle;}/* * Set the additional search paths for the serveez library. The given array of * strings gets @code{svz_free()}d. */voidsvz_dynload_path_set (svz_array_t *paths){  char *str, *env;  int n, len;  /* Return here if necessary. */  if (paths == NULL)    return;  /* Create environment variable. */  env = svz_strdup (DYNLOAD_PATH "=");  len = strlen (env) + 3;  svz_array_foreach (paths, str, n)    {      len = strlen (env) + strlen (str) + 2;      env = svz_realloc (env, len);      strcat (env, str);      env[len - 2] = DYNLOAD_PATH_SEPERATOR;      env[len - 1] = '\0';      svz_free (str);    }  env[len - 2] = '\0';  svz_array_destroy (paths);  /* Set environment variable. */  if (putenv (svz_pstrdup (env)) < 0)    svz_log (LOG_ERROR, "putenv: %s\n", SYS_ERROR);  svz_free (env);}/* * Create an array of strings containing each an additional search path. * The loadpath is hold in the environment variable @samp{SERVEEZ_LOAD_PATH} * which can be set from outside the library or modified using  * @code{svz_dynload_path_set()}. The returned array needs to be destroyed  * after usage. */svz_array_t *svz_dynload_path_get (void){  svz_array_t *paths = svz_array_create (1);  char *path, *p, *start, *val;  int len, n;  svz_array_add (paths, svz_strdup ("."));  if ((p = getenv (DYNLOAD_PATH)) != NULL)    {      while (*p)	{	  start = p;	  while (*p && *p != DYNLOAD_PATH_SEPERATOR)	    p++;	  if (p > start)	    {	      len = p - start;	      path = svz_malloc (len + 1);	      memcpy (path, start, len);	      start = path + len;	      *start-- = 0;	      while ((*start == '/' || *start == '\\') && start > path) 		*start-- = 0;	      /* Do not put duplicate paths here. */	      svz_array_foreach (paths, val, n)		if (!strcmp (val, path))		  {		    svz_free_and_zero (path);		    break;		  }	      if (path)		svz_array_add (paths, path);	    }	  if (*p)	    p++;	}    }  return paths;}/* * Open the given library @var{file} and put it into the currently load  * library list. Return a valid library handle entry on success. */static dyn_library_t *dyn_load_library (char *file){  int n;  void *handle = NULL;  svz_array_t *paths;  char *path;  /* go through all loaded libraries and check if there is such a */  for (n = 0; n < dyn_libraries; n++)    if (!strcmp (dyn_library[n].file, file))      {	dyn_library[n].ref++;	return &dyn_library[n];      }  /* try open the library */  if ((handle = dyn_get_library (NULL, file)) == NULL)    {      paths = svz_dynload_path_get ();      svz_array_foreach (paths, path, n)	if ((handle = dyn_get_library (path, file)) != NULL)	  break;      svz_array_foreach (paths, path, n)	svz_free (path);      svz_array_destroy (paths);    }  if (handle == NULL)    {      svz_log (LOG_ERROR, "link: unable to locate %s\n", file);      return NULL;    }  /* check if this handle already exists */  for (n = 0; n < dyn_libraries; n++)    if (dyn_library[n].handle == handle)      {	dyn_library[n].ref++;	return &dyn_library[n];      }  /* add the shared library to the handle list */  n = dyn_libraries;  dyn_libraries++;  dyn_library = svz_realloc (dyn_library, sizeof (dyn_library_t) * 			     dyn_libraries);  dyn_library[n].file = svz_strdup (file);  dyn_library[n].handle = handle;  dyn_library[n].ref = 1;  return &dyn_library[n];}/* * Unload a given library @var{lib} if possible. Return the reference  * counter or zero if the library has been unloaded. Return -1 if there is  * no such library at all or on other errors. */static intdyn_unload_library (dyn_library_t *lib){  int n, err = 0;  void *handle;  /* check if this library really exists */  for (n = 0; n < dyn_libraries; n++)    if (&dyn_library[n] == lib)      {	/* return the remaining reference counter */	if (--lib->ref > 0)	  return lib->ref;	/* unload the library */	handle = lib->handle;#if HAVE_DLOPEN	err = dlclose (handle);#elif defined (__BEOS__)	err = (unload_add_on ((image_id) handle) != B_OK);#elif HAVE_DLD_LINK	err = dld_unlink_by_file (lib->file);#elif defined (__MINGW32__)	err = (FreeLibrary (handle) == 0);#elif HAVE_SHL_LOAD	err = shl_unload ((shl_t) handle);#elif HAVE_NSADDIMAGE	/* TODO: Find out. */#endif	if (err)	  {	    svz_log (LOG_ERROR, "unlink: %s (%s)\n", dyn_error (), lib->file);	    return -1;	  }	/* rearrange the library structure */	svz_free (lib->file);	if (--dyn_libraries > 0)	  {	    *lib = dyn_library[dyn_libraries];	    svz_realloc (dyn_library, sizeof (dyn_library_t) * dyn_libraries);	  }	else	  {	    svz_free (dyn_library);	    dyn_library = NULL;	  }	return 0;      }  return -1;}/* * Get a function or data symbol @var{symbol} from the given library  * @var{lib}. Return @code{NULL} on errors. */static void *dyn_load_symbol (dyn_library_t *lib, char *symbol){  int n;  void *address = NULL;  /* check if there is such a library */  for (n = 0; n < dyn_libraries; n++)    if (&dyn_library[n] == lib)      {#if HAVE_DLOPEN	address = dlsym (lib->handle, symbol);#elif defined (__BEOS__)	if (get_image_symbol ((image_id) lib->handle, symbol, 			      B_SYMBOL_TYPE_ANY, &address) != B_OK)	  address = NULL;#elif HAVE_DLD_LINK	address = dld_get_func (symbol);#elif defined (__MINGW32__)	*((FARPROC *) &address) = GetProcAddress (lib->handle, symbol);#elif HAVE_SHL_LOAD	if (shl_findsym ((shl_t *) &lib->handle,			 symbol, TYPE_UNDEFINED, &address) != 0)	  address = NULL;#elif HAVE_NSADDIMAGE	address = NSLookupSymbolInImage 	  ((struct mach_header *) lib->handle, symbol,	   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |	   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);        if (address != NULL)          address = NSAddressOfSymbol (address);#endif	if (address == NULL)	  {	    svz_log (LOG_ERROR, "lookup: %s (%s)\n", dyn_error (), symbol);	  }	return address;      }  return NULL;}/* * Finalize the shared library interface of the core library. Unload * all libraries no matter if referenced or not. */voidsvz_dynload_finalize (void){  while (dyn_libraries)    {      dyn_library[0].ref = 1;      dyn_unload_library (&dyn_library[0]);    }}/* * Initialize the shared library interface of the core library. */voidsvz_dynload_init (void){  if (dyn_libraries)    svz_dynload_finalize ();  dyn_libraries = 0;  dyn_library = NULL;}/*  * Create a file name of a shared library for a given servers  * descriptive name @var{description}. */static char *dyn_create_file (char *description){  char *file;  file = svz_malloc (strlen (description) + 		     strlen (DYNLOAD_PREFIX "." DYNLOAD_SUFFIX) + 1);  sprintf (file, DYNLOAD_PREFIX "%s." DYNLOAD_SUFFIX, description);  return file;}/* * Create a symbol name of server definition for a given servers * descriptive name @var{description}. */static char *dyn_create_symbol (char *description){  char *symbol;  symbol = svz_malloc (strlen (description) + 1 +		       strlen (DYNLOAD_SYMBOL_PREFIX "_server_definition"));  sprintf (symbol, DYNLOAD_SYMBOL_PREFIX "%s_server_definition", description);  return symbol;}/* * Load an additional server definition from a shared library. The given * descriptive name @var{description} must be part of the library's name. */svz_servertype_t *svz_servertype_load (char *description){  char *file, *def;  dyn_library_t *lib;  svz_servertype_t *server;  /* load library */  file = dyn_create_file (description);  if ((lib = dyn_load_library (file)) == NULL)    {      svz_free (file);      return NULL;    }  svz_free (file);  /* obtain exported data */  def = dyn_create_symbol (description);  if ((server = dyn_load_symbol (lib, def)) == NULL)    {      dyn_unload_library (lib);      svz_free (def);      return NULL;    }  svz_free (def);  return server;}/* * Unload a server definition from a shared library. The given * descriptive name @var{description} must be part of the library's name. * Return the remaining reference count or -1 on errors. */intsvz_servertype_unload (char *description){  dyn_library_t *lib;  char *file;  /* check if there is such a library loaded */  file = dyn_create_file (description);  if ((lib = dyn_find_library (file)) != NULL)    {      /* try unloading it */      svz_free (file);      return dyn_unload_library (lib);    }  svz_free (file);  return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -