PageRenderTime 109ms CodeModel.GetById 13ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pdsh/ltdl.c

https://code.google.com/
C | 2913 lines | 2759 code | 104 blank | 50 comment | 45 complexity | 270520d0c8c51fe11acdf7caae0aea9f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* ltdl.c -- system independent dlopen wrapper
   2   Copyright (C) 1998, 1999, 2000, 2004, 2005  Free Software Foundation, Inc.
   3   Originally by Thomas Tanner <tanner@ffii.org>
   4   This file is part of GNU Libtool.
   5
   6This library is free software; you can redistribute it and/or
   7modify it under the terms of the GNU Lesser General Public
   8License as published by the Free Software Foundation; either
   9version 2 of the License, or (at your option) any later version.
  10
  11As a special exception to the GNU Lesser General Public License,
  12if you distribute this file as part of a program or library that
  13is built using GNU libtool, you may include it under the same
  14distribution terms that you use for the rest of that program.
  15
  16This library is distributed in the hope that it will be useful,
  17but WITHOUT ANY WARRANTY; without even the implied warranty of
  18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19Lesser General Public License for more details.
  20
  21You should have received a copy of the GNU Lesser General Public
  22License along with this library; if not, write to the Free Software
  23Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  2402110-1301  USA
  25
  26*/
  27
  28#if HAVE_CONFIG_H
  29#  include <config.h>
  30#endif
  31
  32#if HAVE_UNISTD_H
  33#  include <unistd.h>
  34#endif
  35
  36#if HAVE_STDIO_H
  37#  include <stdio.h>
  38#endif
  39
  40/* Include the header defining malloc.  On K&R C compilers,
  41   that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
  42#if HAVE_STDLIB_H
  43#  include <stdlib.h>
  44#else
  45#  if HAVE_MALLOC_H
  46#    include <malloc.h>
  47#  endif
  48#endif
  49
  50#if HAVE_STRING_H
  51#  include <string.h>
  52#else
  53#  if HAVE_STRINGS_H
  54#    include <strings.h>
  55#  endif
  56#endif
  57
  58#if HAVE_CTYPE_H
  59#  include <ctype.h>
  60#endif
  61
  62#if HAVE_MEMORY_H
  63#  include <memory.h>
  64#endif
  65
  66#if HAVE_ERRNO_H
  67#  include <errno.h>
  68#endif
  69
  70
  71#ifndef __WINDOWS__
  72#  ifdef __WIN32__
  73#    define __WINDOWS__
  74#  endif
  75#endif
  76
  77
  78#undef LT_USE_POSIX_DIRENT
  79#ifdef HAVE_CLOSEDIR
  80#  ifdef HAVE_OPENDIR
  81#    ifdef HAVE_READDIR
  82#      ifdef HAVE_DIRENT_H
  83#        define LT_USE_POSIX_DIRENT
  84#      endif /* HAVE_DIRENT_H */
  85#    endif /* HAVE_READDIR */
  86#  endif /* HAVE_OPENDIR */
  87#endif /* HAVE_CLOSEDIR */
  88
  89
  90#undef LT_USE_WINDOWS_DIRENT_EMULATION
  91#ifndef LT_USE_POSIX_DIRENT
  92#  ifdef __WINDOWS__
  93#    define LT_USE_WINDOWS_DIRENT_EMULATION
  94#  endif /* __WINDOWS__ */
  95#endif /* LT_USE_POSIX_DIRENT */
  96
  97
  98#ifdef LT_USE_POSIX_DIRENT
  99#  include <dirent.h>
 100#  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
 101#else
 102#  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
 103#    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
 104#  else
 105#    define dirent direct
 106#    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
 107#    if HAVE_SYS_NDIR_H
 108#      include <sys/ndir.h>
 109#    endif
 110#    if HAVE_SYS_DIR_H
 111#      include <sys/dir.h>
 112#    endif
 113#    if HAVE_NDIR_H
 114#      include <ndir.h>
 115#    endif
 116#  endif
 117#endif
 118
 119#if HAVE_ARGZ_H
 120#  include <argz.h>
 121#endif
 122
 123#if HAVE_ASSERT_H
 124#  include <assert.h>
 125#else
 126#  define assert(arg)	((void) 0)
 127#endif
 128
 129#include "ltdl.h"
 130
 131#if WITH_DMALLOC
 132#  include <dmalloc.h>
 133#endif
 134
 135
 136
 137
 138/* --- WINDOWS SUPPORT --- */
 139
 140
 141#ifdef DLL_EXPORT
 142#  define LT_GLOBAL_DATA	__declspec(dllexport)
 143#else
 144#  define LT_GLOBAL_DATA
 145#endif
 146
 147/* fopen() mode flags for reading a text file */
 148#undef	LT_READTEXT_MODE
 149#ifdef __WINDOWS__
 150#  define LT_READTEXT_MODE "rt"
 151#else
 152#  define LT_READTEXT_MODE "r"
 153#endif
 154
 155#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
 156
 157#include <windows.h>
 158
 159#define dirent lt_dirent
 160#define DIR lt_DIR
 161
 162struct dirent
 163{
 164  char d_name[2048];
 165  int  d_namlen;
 166};
 167
 168typedef struct _DIR
 169{
 170  HANDLE hSearch;
 171  WIN32_FIND_DATA Win32FindData;
 172  BOOL firsttime;
 173  struct dirent file_info;
 174} DIR;
 175
 176#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
 177
 178
 179/* --- MANIFEST CONSTANTS --- */
 180
 181
 182/* Standard libltdl search path environment variable name  */
 183#undef  LTDL_SEARCHPATH_VAR
 184#define LTDL_SEARCHPATH_VAR	"LTDL_LIBRARY_PATH"
 185
 186/* Standard libtool archive file extension.  */
 187#undef  LTDL_ARCHIVE_EXT
 188#define LTDL_ARCHIVE_EXT	".la"
 189
 190/* max. filename length */
 191#ifndef LT_FILENAME_MAX
 192#  define LT_FILENAME_MAX	1024
 193#endif
 194
 195/* This is the maximum symbol size that won't require malloc/free */
 196#undef	LT_SYMBOL_LENGTH
 197#define LT_SYMBOL_LENGTH	128
 198
 199/* This accounts for the _LTX_ separator */
 200#undef	LT_SYMBOL_OVERHEAD
 201#define LT_SYMBOL_OVERHEAD	5
 202
 203
 204
 205
 206/* --- MEMORY HANDLING --- */
 207
 208
 209/* These are the functions used internally.  In addition to making
 210   use of the associated function pointers above, they also perform
 211   error handling.  */
 212static char   *lt_estrdup	LT_PARAMS((const char *str));
 213static lt_ptr lt_emalloc	LT_PARAMS((size_t size));
 214static lt_ptr lt_erealloc	LT_PARAMS((lt_ptr addr, size_t size));
 215
 216/* static lt_ptr rpl_realloc	LT_PARAMS((lt_ptr ptr, size_t size)); */
 217#define rpl_realloc realloc
 218
 219/* These are the pointers that can be changed by the caller:  */
 220LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)	LT_PARAMS((size_t size))
 221 			= (lt_ptr (*) LT_PARAMS((size_t))) malloc;
 222LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)	LT_PARAMS((lt_ptr ptr, size_t size))
 223 			= (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
 224LT_GLOBAL_DATA void   (*lt_dlfree)	LT_PARAMS((lt_ptr ptr))
 225 			= (void (*) LT_PARAMS((lt_ptr))) free;
 226
 227/* The following macros reduce the amount of typing needed to cast
 228   assigned memory.  */
 229#if WITH_DMALLOC
 230
 231#define LT_DLMALLOC(tp, n)	((tp *) xmalloc ((n) * sizeof(tp)))
 232#define LT_DLREALLOC(tp, p, n)	((tp *) xrealloc ((p), (n) * sizeof(tp)))
 233#define LT_DLFREE(p)						\
 234	LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
 235
 236#define LT_EMALLOC(tp, n)	((tp *) xmalloc ((n) * sizeof(tp)))
 237#define LT_EREALLOC(tp, p, n)	((tp *) xrealloc ((p), (n) * sizeof(tp)))
 238
 239#else
 240
 241#define LT_DLMALLOC(tp, n)	((tp *) lt_dlmalloc ((n) * sizeof(tp)))
 242#define LT_DLREALLOC(tp, p, n)	((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
 243#define LT_DLFREE(p)						\
 244	LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
 245
 246#define LT_EMALLOC(tp, n)	((tp *) lt_emalloc ((n) * sizeof(tp)))
 247#define LT_EREALLOC(tp, p, n)	((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
 248
 249#endif
 250
 251#define LT_DLMEM_REASSIGN(p, q)			LT_STMT_START {	\
 252	if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }	\
 253						} LT_STMT_END
 254
 255
 256/* --- REPLACEMENT FUNCTIONS --- */
 257
 258
 259#undef strdup
 260#define strdup rpl_strdup
 261
 262static char *strdup LT_PARAMS((const char *str));
 263
 264static char *
 265strdup(str)
 266     const char *str;
 267{
 268  char *tmp = 0;
 269
 270  if (str)
 271    {
 272      tmp = LT_DLMALLOC (char, 1+ strlen (str));
 273      if (tmp)
 274	{
 275	  strcpy(tmp, str);
 276	}
 277    }
 278
 279  return tmp;
 280}
 281
 282
 283#if ! HAVE_STRCMP
 284
 285#undef strcmp
 286#define strcmp rpl_strcmp
 287
 288static int strcmp LT_PARAMS((const char *str1, const char *str2));
 289
 290static int
 291strcmp (str1, str2)
 292     const char *str1;
 293     const char *str2;
 294{
 295  if (str1 == str2)
 296    return 0;
 297  if (str1 == 0)
 298    return -1;
 299  if (str2 == 0)
 300    return 1;
 301
 302  for (;*str1 && *str2; ++str1, ++str2)
 303    {
 304      if (*str1 != *str2)
 305	break;
 306    }
 307
 308  return (int)(*str1 - *str2);
 309}
 310#endif
 311
 312
 313#if ! HAVE_STRCHR
 314
 315#  if HAVE_INDEX
 316#    define strchr index
 317#  else
 318#    define strchr rpl_strchr
 319
 320static const char *strchr LT_PARAMS((const char *str, int ch));
 321
 322static const char*
 323strchr(str, ch)
 324     const char *str;
 325     int ch;
 326{
 327  const char *p;
 328
 329  for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
 330    /*NOWORK*/;
 331
 332  return (*p == (char)ch) ? p : 0;
 333}
 334
 335#  endif
 336#endif /* !HAVE_STRCHR */
 337
 338
 339#if ! HAVE_STRRCHR
 340
 341#  if HAVE_RINDEX
 342#    define strrchr rindex
 343#  else
 344#    define strrchr rpl_strrchr
 345
 346static const char *strrchr LT_PARAMS((const char *str, int ch));
 347
 348static const char*
 349strrchr(str, ch)
 350     const char *str;
 351     int ch;
 352{
 353  const char *p, *q = 0;
 354
 355  for (p = str; *p != LT_EOS_CHAR; ++p)
 356    {
 357      if (*p == (char) ch)
 358	{
 359	  q = p;
 360	}
 361    }
 362
 363  return q;
 364}
 365
 366# endif
 367#endif
 368
 369/* NOTE:  Neither bcopy nor the memcpy implementation below can
 370          reliably handle copying in overlapping areas of memory.  Use
 371          memmove (for which there is a fallback implmentation below)
 372	  if you need that behaviour.  */
 373#if ! HAVE_MEMCPY
 374
 375#  if HAVE_BCOPY
 376#    define memcpy(dest, src, size)	bcopy (src, dest, size)
 377#  else
 378#    define memcpy rpl_memcpy
 379
 380static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
 381
 382static lt_ptr
 383memcpy (dest, src, size)
 384     lt_ptr dest;
 385     const lt_ptr src;
 386     size_t size;
 387{
 388  const char *	s = src;
 389  char *	d = dest;
 390  size_t	i = 0;
 391
 392  for (i = 0; i < size; ++i)
 393    {
 394      d[i] = s[i];
 395    }
 396
 397  return dest;
 398}
 399
 400#  endif /* !HAVE_BCOPY */
 401#endif   /* !HAVE_MEMCPY */
 402
 403#if ! HAVE_MEMMOVE
 404#  define memmove rpl_memmove
 405
 406static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
 407
 408static lt_ptr
 409memmove (dest, src, size)
 410     lt_ptr dest;
 411     const lt_ptr src;
 412     size_t size;
 413{
 414  const char *	s = src;
 415  char *	d = dest;
 416  size_t	i;
 417
 418  if (d < s)
 419    for (i = 0; i < size; ++i)
 420      {
 421	d[i] = s[i];
 422      }
 423  else if (d > s && size > 0)
 424    for (i = size -1; ; --i)
 425      {
 426	d[i] = s[i];
 427	if (i == 0)
 428	  break;
 429      }
 430
 431  return dest;
 432}
 433
 434#endif /* !HAVE_MEMMOVE */
 435
 436#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
 437
 438static void closedir LT_PARAMS((DIR *entry));
 439
 440static void
 441closedir(entry)
 442  DIR *entry;
 443{
 444  assert(entry != (DIR *) NULL);
 445  FindClose(entry->hSearch);
 446  lt_dlfree((lt_ptr)entry);
 447}
 448
 449
 450static DIR * opendir LT_PARAMS((const char *path));
 451
 452static DIR*
 453opendir (path)
 454  const char *path;
 455{
 456  char file_specification[LT_FILENAME_MAX];
 457  DIR *entry;
 458
 459  assert(path != (char *) NULL);
 460  /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
 461  (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
 462  file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
 463  (void) strcat(file_specification,"\\");
 464  entry = LT_DLMALLOC (DIR,sizeof(DIR));
 465  if (entry != (DIR *) 0)
 466    {
 467      entry->firsttime = TRUE;
 468      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
 469    }
 470  if (entry->hSearch == INVALID_HANDLE_VALUE)
 471    {
 472      (void) strcat(file_specification,"\\*.*");
 473      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
 474      if (entry->hSearch == INVALID_HANDLE_VALUE)
 475        {
 476          LT_DLFREE (entry);
 477          return (DIR *) 0;
 478        }
 479    }
 480  return(entry);
 481}
 482
 483
 484static struct dirent *readdir LT_PARAMS((DIR *entry));
 485
 486static struct dirent *readdir(entry)
 487  DIR *entry;
 488{
 489  int
 490    status;
 491
 492  if (entry == (DIR *) 0)
 493    return((struct dirent *) 0);
 494  if (!entry->firsttime)
 495    {
 496      status = FindNextFile(entry->hSearch,&entry->Win32FindData);
 497      if (status == 0)
 498        return((struct dirent *) 0);
 499    }
 500  entry->firsttime = FALSE;
 501  (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
 502    LT_FILENAME_MAX-1);
 503  entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
 504  entry->file_info.d_namlen = strlen(entry->file_info.d_name);
 505  return(&entry->file_info);
 506}
 507
 508#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
 509
 510/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
 511    ``realloc is not entirely portable''
 512   In any case we want to use the allocator supplied by the user without
 513   burdening them with an lt_dlrealloc function pointer to maintain.
 514   Instead implement our own version (with known boundary conditions)
 515   using lt_dlmalloc and lt_dlfree. */
 516
 517/* #undef realloc
 518   #define realloc rpl_realloc
 519*/
 520#if 0
 521  /* You can't (re)define realloc unless you also (re)define malloc.
 522     Right now, this code uses the size of the *destination* to decide
 523     how much to copy.  That's not right, but you can't know the size
 524     of the source unless you know enough about, or wrote malloc.  So
 525     this code is disabled... */
 526
 527static lt_ptr
 528realloc (ptr, size)
 529     lt_ptr ptr;
 530     size_t size;
 531{
 532  if (size == 0)
 533    {
 534      /* For zero or less bytes, free the original memory */
 535      if (ptr != 0)
 536	{
 537	  lt_dlfree (ptr);
 538	}
 539
 540      return (lt_ptr) 0;
 541    }
 542  else if (ptr == 0)
 543    {
 544      /* Allow reallocation of a NULL pointer.  */
 545      return lt_dlmalloc (size);
 546    }
 547  else
 548    {
 549      /* Allocate a new block, copy and free the old block.  */
 550      lt_ptr mem = lt_dlmalloc (size);
 551
 552      if (mem)
 553	{
 554	  memcpy (mem, ptr, size);
 555	  lt_dlfree (ptr);
 556	}
 557
 558      /* Note that the contents of PTR are not damaged if there is
 559	 insufficient memory to realloc.  */
 560      return mem;
 561    }
 562}
 563#endif
 564
 565
 566#if ! HAVE_ARGZ_APPEND
 567#  define argz_append rpl_argz_append
 568
 569static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
 570					const char *buf, size_t buf_len));
 571
 572static error_t
 573argz_append (pargz, pargz_len, buf, buf_len)
 574     char **pargz;
 575     size_t *pargz_len;
 576     const char *buf;
 577     size_t buf_len;
 578{
 579  size_t argz_len;
 580  char  *argz;
 581
 582  assert (pargz);
 583  assert (pargz_len);
 584  assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
 585
 586  /* If nothing needs to be appended, no more work is required.  */
 587  if (buf_len == 0)
 588    return 0;
 589
 590  /* Ensure there is enough room to append BUF_LEN.  */
 591  argz_len = *pargz_len + buf_len;
 592  argz = LT_DLREALLOC (char, *pargz, argz_len);
 593  if (!argz)
 594    return ENOMEM;
 595
 596  /* Copy characters from BUF after terminating '\0' in ARGZ.  */
 597  memcpy (argz + *pargz_len, buf, buf_len);
 598
 599  /* Assign new values.  */
 600  *pargz = argz;
 601  *pargz_len = argz_len;
 602
 603  return 0;
 604}
 605#endif /* !HAVE_ARGZ_APPEND */
 606
 607
 608#if ! HAVE_ARGZ_CREATE_SEP
 609#  define argz_create_sep rpl_argz_create_sep
 610
 611static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
 612					    char **pargz, size_t *pargz_len));
 613
 614static error_t
 615argz_create_sep (str, delim, pargz, pargz_len)
 616     const char *str;
 617     int delim;
 618     char **pargz;
 619     size_t *pargz_len;
 620{
 621  size_t argz_len;
 622  char *argz = 0;
 623
 624  assert (str);
 625  assert (pargz);
 626  assert (pargz_len);
 627
 628  /* Make a copy of STR, but replacing each occurrence of
 629     DELIM with '\0'.  */
 630  argz_len = 1+ LT_STRLEN (str);
 631  if (argz_len)
 632    {
 633      const char *p;
 634      char *q;
 635
 636      argz = LT_DLMALLOC (char, argz_len);
 637      if (!argz)
 638	return ENOMEM;
 639
 640      for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
 641	{
 642	  if (*p == delim)
 643	    {
 644	      /* Ignore leading delimiters, and fold consecutive
 645		 delimiters in STR into a single '\0' in ARGZ.  */
 646	      if ((q > argz) && (q[-1] != LT_EOS_CHAR))
 647		*q++ = LT_EOS_CHAR;
 648	      else
 649		--argz_len;
 650	    }
 651	  else
 652	    *q++ = *p;
 653	}
 654      /* Copy terminating LT_EOS_CHAR.  */
 655      *q = *p;
 656    }
 657
 658  /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
 659  if (!argz_len)
 660    LT_DLFREE (argz);
 661
 662  /* Assign new values.  */
 663  *pargz = argz;
 664  *pargz_len = argz_len;
 665
 666  return 0;
 667}
 668#endif /* !HAVE_ARGZ_CREATE_SEP */
 669
 670
 671#if ! HAVE_ARGZ_INSERT
 672#  define argz_insert rpl_argz_insert
 673
 674static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
 675					char *before, const char *entry));
 676
 677static error_t
 678argz_insert (pargz, pargz_len, before, entry)
 679     char **pargz;
 680     size_t *pargz_len;
 681     char *before;
 682     const char *entry;
 683{
 684  assert (pargz);
 685  assert (pargz_len);
 686  assert (entry && *entry);
 687
 688  /* No BEFORE address indicates ENTRY should be inserted after the
 689     current last element.  */
 690  if (!before)
 691    return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
 692
 693  /* This probably indicates a programmer error, but to preserve
 694     semantics, scan back to the start of an entry if BEFORE points
 695     into the middle of it.  */
 696  while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
 697    --before;
 698
 699  {
 700    size_t entry_len	= 1+ LT_STRLEN (entry);
 701    size_t argz_len	= *pargz_len + entry_len;
 702    size_t offset	= before - *pargz;
 703    char   *argz	= LT_DLREALLOC (char, *pargz, argz_len);
 704
 705    if (!argz)
 706      return ENOMEM;
 707
 708    /* Make BEFORE point to the equivalent offset in ARGZ that it
 709       used to have in *PARGZ incase realloc() moved the block.  */
 710    before = argz + offset;
 711
 712    /* Move the ARGZ entries starting at BEFORE up into the new
 713       space at the end -- making room to copy ENTRY into the
 714       resulting gap.  */
 715    memmove (before + entry_len, before, *pargz_len - offset);
 716    memcpy  (before, entry, entry_len);
 717
 718    /* Assign new values.  */
 719    *pargz = argz;
 720    *pargz_len = argz_len;
 721  }
 722
 723  return 0;
 724}
 725#endif /* !HAVE_ARGZ_INSERT */
 726
 727
 728#if ! HAVE_ARGZ_NEXT
 729#  define argz_next rpl_argz_next
 730
 731static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
 732				    const char *entry));
 733
 734static char *
 735argz_next (argz, argz_len, entry)
 736     char *argz;
 737     size_t argz_len;
 738     const char *entry;
 739{
 740  assert ((argz && argz_len) || (!argz && !argz_len));
 741
 742  if (entry)
 743    {
 744      /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
 745	 within the ARGZ vector.  */
 746      assert ((!argz && !argz_len)
 747	      || ((argz <= entry) && (entry < (argz + argz_len))));
 748
 749      /* Move to the char immediately after the terminating
 750	 '\0' of ENTRY.  */
 751      entry = 1+ strchr (entry, LT_EOS_CHAR);
 752
 753      /* Return either the new ENTRY, or else NULL if ARGZ is
 754	 exhausted.  */
 755      return (entry >= argz + argz_len) ? 0 : (char *) entry;
 756    }
 757  else
 758    {
 759      /* This should probably be flagged as a programmer error,
 760	 since starting an argz_next loop with the iterator set
 761	 to ARGZ is safer.  To preserve semantics, handle the NULL
 762	 case by returning the start of ARGZ (if any).  */
 763      if (argz_len > 0)
 764	return argz;
 765      else
 766	return 0;
 767    }
 768}
 769#endif /* !HAVE_ARGZ_NEXT */
 770
 771
 772
 773#if ! HAVE_ARGZ_STRINGIFY
 774#  define argz_stringify rpl_argz_stringify
 775
 776static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
 777				       int sep));
 778
 779static void
 780argz_stringify (argz, argz_len, sep)
 781     char *argz;
 782     size_t argz_len;
 783     int sep;
 784{
 785  assert ((argz && argz_len) || (!argz && !argz_len));
 786
 787  if (sep)
 788    {
 789      --argz_len;		/* don't stringify the terminating EOS */
 790      while (--argz_len > 0)
 791	{
 792	  if (argz[argz_len] == LT_EOS_CHAR)
 793	    argz[argz_len] = sep;
 794	}
 795    }
 796}
 797#endif /* !HAVE_ARGZ_STRINGIFY */
 798
 799
 800
 801
 802/* --- TYPE DEFINITIONS -- */
 803
 804
 805/* This type is used for the array of caller data sets in each handler. */
 806typedef struct {
 807  lt_dlcaller_id	key;
 808  lt_ptr		data;
 809} lt_caller_data;
 810
 811
 812
 813
 814/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
 815
 816
 817/* Extract the diagnostic strings from the error table macro in the same
 818   order as the enumerated indices in ltdl.h. */
 819
 820static const char *lt_dlerror_strings[] =
 821  {
 822#define LT_ERROR(name, diagnostic)	(diagnostic),
 823    lt_dlerror_table
 824#undef LT_ERROR
 825
 826    0
 827  };
 828
 829/* This structure is used for the list of registered loaders. */
 830struct lt_dlloader {
 831  struct lt_dlloader   *next;
 832  const char	       *loader_name;	/* identifying name for each loader */
 833  const char	       *sym_prefix;	/* prefix for symbols */
 834  lt_module_open       *module_open;
 835  lt_module_close      *module_close;
 836  lt_find_sym	       *find_sym;
 837  lt_dlloader_exit     *dlloader_exit;
 838  lt_user_data		dlloader_data;
 839};
 840
 841struct lt_dlhandle_struct {
 842  struct lt_dlhandle_struct   *next;
 843  lt_dlloader	       *loader;		/* dlopening interface */
 844  lt_dlinfo		info;
 845  int			depcount;	/* number of dependencies */
 846  lt_dlhandle	       *deplibs;	/* dependencies */
 847  lt_module		module;		/* system module handle */
 848  lt_ptr		system;		/* system specific data */
 849  lt_caller_data       *caller_data;	/* per caller associated data */
 850  int			flags;		/* various boolean stats */
 851};
 852
 853/* Various boolean flags can be stored in the flags field of an
 854   lt_dlhandle_struct... */
 855#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
 856#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
 857
 858#define LT_DLRESIDENT_FLAG	    (0x01 << 0)
 859/* ...add more flags here... */
 860
 861#define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
 862
 863
 864#define LT_DLSTRERROR(name)	lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
 865
 866static	const char	objdir[]		= LTDL_OBJDIR;
 867static	const char	archive_ext[]		= LTDL_ARCHIVE_EXT;
 868#ifdef	LTDL_SHLIB_EXT
 869static	const char	shlib_ext[]		= LTDL_SHLIB_EXT;
 870#endif
 871#ifdef	LTDL_SYSSEARCHPATH
 872static	const char	sys_search_path[]	= LTDL_SYSSEARCHPATH;
 873#endif
 874
 875
 876
 877
 878/* --- MUTEX LOCKING --- */
 879
 880
 881/* Macros to make it easier to run the lock functions only if they have
 882   been registered.  The reason for the complicated lock macro is to
 883   ensure that the stored error message from the last error is not
 884   accidentally erased if the current function doesn't generate an
 885   error of its own.  */
 886#define LT_DLMUTEX_LOCK()			LT_STMT_START {	\
 887	if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();	\
 888						} LT_STMT_END
 889#define LT_DLMUTEX_UNLOCK()			LT_STMT_START { \
 890	if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
 891						} LT_STMT_END
 892#define LT_DLMUTEX_SETERROR(errormsg)		LT_STMT_START {	\
 893	if (lt_dlmutex_seterror_func)				\
 894		(*lt_dlmutex_seterror_func) (errormsg);		\
 895	else 	lt_dllast_error = (errormsg);	} LT_STMT_END
 896#define LT_DLMUTEX_GETERROR(errormsg)		LT_STMT_START {	\
 897	if (lt_dlmutex_geterror_func)				\
 898		(errormsg) = (*lt_dlmutex_geterror_func) ();	\
 899	else	(errormsg) = lt_dllast_error;	} LT_STMT_END
 900
 901/* The mutex functions stored here are global, and are necessarily the
 902   same for all threads that wish to share access to libltdl.  */
 903static	lt_dlmutex_lock	    *lt_dlmutex_lock_func     = 0;
 904static	lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
 905static	lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
 906static	lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
 907static	const char	    *lt_dllast_error	      = 0;
 908
 909
 910/* Either set or reset the mutex functions.  Either all the arguments must
 911   be valid functions, or else all can be NULL to turn off locking entirely.
 912   The registered functions should be manipulating a static global lock
 913   from the lock() and unlock() callbacks, which needs to be reentrant.  */
 914int
 915lt_dlmutex_register (lock, unlock, seterror, geterror)
 916     lt_dlmutex_lock *lock;
 917     lt_dlmutex_unlock *unlock;
 918     lt_dlmutex_seterror *seterror;
 919     lt_dlmutex_geterror *geterror;
 920{
 921  lt_dlmutex_unlock *old_unlock = unlock;
 922  int		     errors	= 0;
 923
 924  /* Lock using the old lock() callback, if any.  */
 925  LT_DLMUTEX_LOCK ();
 926
 927  if ((lock && unlock && seterror && geterror)
 928      || !(lock || unlock || seterror || geterror))
 929    {
 930      lt_dlmutex_lock_func     = lock;
 931      lt_dlmutex_unlock_func   = unlock;
 932      lt_dlmutex_geterror_func = geterror;
 933    }
 934  else
 935    {
 936      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
 937      ++errors;
 938    }
 939
 940  /* Use the old unlock() callback we saved earlier, if any.  Otherwise
 941     record any errors using internal storage.  */
 942  if (old_unlock)
 943    (*old_unlock) ();
 944
 945  /* Return the number of errors encountered during the execution of
 946     this function.  */
 947  return errors;
 948}
 949
 950
 951
 952
 953/* --- ERROR HANDLING --- */
 954
 955
 956static	const char    **user_error_strings	= 0;
 957static	int		errorcount		= LT_ERROR_MAX;
 958
 959int
 960lt_dladderror (diagnostic)
 961     const char *diagnostic;
 962{
 963  int		errindex = 0;
 964  int		result	 = -1;
 965  const char  **temp     = (const char **) 0;
 966
 967  assert (diagnostic);
 968
 969  LT_DLMUTEX_LOCK ();
 970
 971  errindex = errorcount - LT_ERROR_MAX;
 972  temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
 973  if (temp)
 974    {
 975      user_error_strings		= temp;
 976      user_error_strings[errindex]	= diagnostic;
 977      result				= errorcount++;
 978    }
 979
 980  LT_DLMUTEX_UNLOCK ();
 981
 982  return result;
 983}
 984
 985int
 986lt_dlseterror (errindex)
 987     int errindex;
 988{
 989  int		errors	 = 0;
 990
 991  LT_DLMUTEX_LOCK ();
 992
 993  if (errindex >= errorcount || errindex < 0)
 994    {
 995      /* Ack!  Error setting the error message! */
 996      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
 997      ++errors;
 998    }
 999  else if (errindex < LT_ERROR_MAX)
1000    {
1001      /* No error setting the error message! */
1002      LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
1003    }
1004  else
1005    {
1006      /* No error setting the error message! */
1007      LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
1008    }
1009
1010  LT_DLMUTEX_UNLOCK ();
1011
1012  return errors;
1013}
1014
1015static lt_ptr
1016lt_emalloc (size)
1017     size_t size;
1018{
1019  lt_ptr mem = lt_dlmalloc (size);
1020  if (size && !mem)
1021    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1022  return mem;
1023}
1024
1025static lt_ptr
1026lt_erealloc (addr, size)
1027     lt_ptr addr;
1028     size_t size;
1029{
1030  lt_ptr mem = lt_dlrealloc (addr, size);
1031  if (size && !mem)
1032    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1033  return mem;
1034}
1035
1036static char *
1037lt_estrdup (str)
1038     const char *str;
1039{
1040  char *copy = strdup (str);
1041  if (LT_STRLEN (str) && !copy)
1042    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1043  return copy;
1044}
1045
1046
1047
1048
1049/* --- DLOPEN() INTERFACE LOADER --- */
1050
1051
1052#if HAVE_LIBDL
1053
1054/* dynamic linking with dlopen/dlsym */
1055
1056#if HAVE_DLFCN_H
1057#  include <dlfcn.h>
1058#endif
1059
1060#if HAVE_SYS_DL_H
1061#  include <sys/dl.h>
1062#endif
1063
1064#ifdef RTLD_GLOBAL
1065#  define LT_GLOBAL		RTLD_GLOBAL
1066#else
1067#  ifdef DL_GLOBAL
1068#    define LT_GLOBAL		DL_GLOBAL
1069#  endif
1070#endif /* !RTLD_GLOBAL */
1071#ifndef LT_GLOBAL
1072#  define LT_GLOBAL		0
1073#endif /* !LT_GLOBAL */
1074
1075/* We may have to define LT_LAZY_OR_NOW in the command line if we
1076   find out it does not work in some platform. */
1077#ifndef LT_LAZY_OR_NOW
1078#  ifdef RTLD_LAZY
1079#    define LT_LAZY_OR_NOW	RTLD_LAZY
1080#  else
1081#    ifdef DL_LAZY
1082#      define LT_LAZY_OR_NOW	DL_LAZY
1083#    endif
1084#  endif /* !RTLD_LAZY */
1085#endif
1086#ifndef LT_LAZY_OR_NOW
1087#  ifdef RTLD_NOW
1088#    define LT_LAZY_OR_NOW	RTLD_NOW
1089#  else
1090#    ifdef DL_NOW
1091#      define LT_LAZY_OR_NOW	DL_NOW
1092#    endif
1093#  endif /* !RTLD_NOW */
1094#endif
1095#ifndef LT_LAZY_OR_NOW
1096#  define LT_LAZY_OR_NOW	0
1097#endif /* !LT_LAZY_OR_NOW */
1098
1099#if HAVE_DLERROR
1100#  define DLERROR(arg)	dlerror ()
1101#else
1102#  define DLERROR(arg)	LT_DLSTRERROR (arg)
1103#endif
1104
1105static lt_module
1106sys_dl_open (loader_data, filename)
1107     lt_user_data loader_data;
1108     const char *filename;
1109{
1110  lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1111
1112  if (!module)
1113    {
1114      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1115    }
1116
1117  return module;
1118}
1119
1120static int
1121sys_dl_close (loader_data, module)
1122     lt_user_data loader_data;
1123     lt_module module;
1124{
1125  int errors = 0;
1126
1127  if (dlclose (module) != 0)
1128    {
1129      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1130      ++errors;
1131    }
1132
1133  return errors;
1134}
1135
1136static lt_ptr
1137sys_dl_sym (loader_data, module, symbol)
1138     lt_user_data loader_data;
1139     lt_module module;
1140     const char *symbol;
1141{
1142  lt_ptr address = dlsym (module, symbol);
1143
1144  if (!address)
1145    {
1146      LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1147    }
1148
1149  return address;
1150}
1151
1152static struct lt_user_dlloader sys_dl =
1153  {
1154#  ifdef NEED_USCORE
1155    "_",
1156#  else
1157    0,
1158#  endif
1159    sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1160
1161
1162#endif /* HAVE_LIBDL */
1163
1164
1165
1166/* --- SHL_LOAD() INTERFACE LOADER --- */
1167
1168#if HAVE_SHL_LOAD
1169
1170/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1171
1172#ifdef HAVE_DL_H
1173#  include <dl.h>
1174#endif
1175
1176/* some flags are missing on some systems, so we provide
1177 * harmless defaults.
1178 *
1179 * Mandatory:
1180 * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
1181 * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
1182 *
1183 * Optionally:
1184 * BIND_FIRST	   - Place the library at the head of the symbol search
1185 * 		     order.
1186 * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
1187 * 		     unsatisfied symbols as fatal.  This flag allows
1188 * 		     binding of unsatisfied code symbols to be deferred
1189 * 		     until use.
1190 *		     [Perl: For certain libraries, like DCE, deferred
1191 *		     binding often causes run time problems. Adding
1192 *		     BIND_NONFATAL to BIND_IMMEDIATE still allows
1193 *		     unresolved references in situations like this.]
1194 * BIND_NOSTART	   - Do not call the initializer for the shared library
1195 *		     when the library is loaded, nor on a future call to
1196 *		     shl_unload().
1197 * BIND_VERBOSE	   - Print verbose messages concerning possible
1198 *		     unsatisfied symbols.
1199 *
1200 * hp9000s700/hp9000s800:
1201 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1202 *		     present at library load time.
1203 * DYNAMIC_PATH	   - Allow the loader to dynamically search for the
1204 *		     library specified by the path argument.
1205 */
1206
1207#ifndef	DYNAMIC_PATH
1208#  define DYNAMIC_PATH		0
1209#endif
1210#ifndef	BIND_RESTRICTED
1211#  define BIND_RESTRICTED	0
1212#endif
1213
1214#define	LT_BIND_FLAGS	(BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1215
1216static lt_module
1217sys_shl_open (loader_data, filename)
1218     lt_user_data loader_data;
1219     const char *filename;
1220{
1221  static shl_t self = (shl_t) 0;
1222  lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1223
1224  /* Since searching for a symbol against a NULL module handle will also
1225     look in everything else that was already loaded and exported with
1226     the -E compiler flag, we always cache a handle saved before any
1227     modules are loaded.  */
1228  if (!self)
1229    {
1230      lt_ptr address;
1231      shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1232    }
1233
1234  if (!filename)
1235    {
1236      module = self;
1237    }
1238  else
1239    {
1240      module = shl_load (filename, LT_BIND_FLAGS, 0L);
1241
1242      if (!module)
1243	{
1244	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1245	}
1246    }
1247
1248  return module;
1249}
1250
1251static int
1252sys_shl_close (loader_data, module)
1253     lt_user_data loader_data;
1254     lt_module module;
1255{
1256  int errors = 0;
1257
1258  if (module && (shl_unload ((shl_t) (module)) != 0))
1259    {
1260      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1261      ++errors;
1262    }
1263
1264  return errors;
1265}
1266
1267static lt_ptr
1268sys_shl_sym (loader_data, module, symbol)
1269     lt_user_data loader_data;
1270     lt_module module;
1271     const char *symbol;
1272{
1273  lt_ptr address = 0;
1274
1275  /* sys_shl_open should never return a NULL module handle */
1276  if (module == (lt_module) 0)
1277  {
1278    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1279  }
1280  else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1281    {
1282      if (!address)
1283	{
1284	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1285	}
1286    }
1287
1288  return address;
1289}
1290
1291static struct lt_user_dlloader sys_shl = {
1292  0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1293};
1294
1295#endif /* HAVE_SHL_LOAD */
1296
1297
1298
1299
1300/* --- LOADLIBRARY() INTERFACE LOADER --- */
1301
1302#ifdef __WINDOWS__
1303
1304/* dynamic linking for Win32 */
1305
1306#include <windows.h>
1307
1308/* Forward declaration; required to implement handle search below. */
1309static lt_dlhandle handles;
1310
1311static lt_module
1312sys_wll_open (loader_data, filename)
1313     lt_user_data loader_data;
1314     const char *filename;
1315{
1316  lt_dlhandle	cur;
1317  lt_module	module	   = 0;
1318  const char   *errormsg   = 0;
1319  char	       *searchname = 0;
1320  char	       *ext;
1321  char		self_name_buf[MAX_PATH];
1322
1323  if (!filename)
1324    {
1325      /* Get the name of main module */
1326      *self_name_buf = 0;
1327      GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1328      filename = ext = self_name_buf;
1329    }
1330  else
1331    {
1332      ext = strrchr (filename, '.');
1333    }
1334
1335  if (ext)
1336    {
1337      /* FILENAME already has an extension. */
1338      searchname = lt_estrdup (filename);
1339    }
1340  else
1341    {
1342      /* Append a `.' to stop Windows from adding an
1343	 implicit `.dll' extension. */
1344      searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1345      if (searchname)
1346	sprintf (searchname, "%s.", filename);
1347    }
1348  if (!searchname)
1349    return 0;
1350
1351  {
1352    /* Silence dialog from LoadLibrary on some failures.
1353       No way to get the error mode, but to set it,
1354       so set it twice to preserve any previous flags. */
1355    UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
1356    SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
1357
1358#if defined(__CYGWIN__)
1359    {
1360      char wpath[MAX_PATH];
1361      cygwin_conv_to_full_win32_path (searchname, wpath);
1362      module = LoadLibrary (wpath);
1363    }
1364#else
1365    module = LoadLibrary (searchname);
1366#endif
1367
1368    /* Restore the error mode. */
1369    SetErrorMode(errormode);
1370  }
1371
1372  LT_DLFREE (searchname);
1373
1374  /* libltdl expects this function to fail if it is unable
1375     to physically load the library.  Sadly, LoadLibrary
1376     will search the loaded libraries for a match and return
1377     one of them if the path search load fails.
1378
1379     We check whether LoadLibrary is returning a handle to
1380     an already loaded module, and simulate failure if we
1381     find one. */
1382  LT_DLMUTEX_LOCK ();
1383  cur = handles;
1384  while (cur)
1385    {
1386      if (!cur->module)
1387	{
1388	  cur = 0;
1389	  break;
1390	}
1391
1392      if (cur->module == module)
1393	{
1394	  break;
1395	}
1396
1397      cur = cur->next;
1398  }
1399  LT_DLMUTEX_UNLOCK ();
1400
1401  if (cur || !module)
1402    {
1403      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1404      module = 0;
1405    }
1406
1407  return module;
1408}
1409
1410static int
1411sys_wll_close (loader_data, module)
1412     lt_user_data loader_data;
1413     lt_module module;
1414{
1415  int	      errors   = 0;
1416
1417  if (FreeLibrary(module) == 0)
1418    {
1419      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1420      ++errors;
1421    }
1422
1423  return errors;
1424}
1425
1426static lt_ptr
1427sys_wll_sym (loader_data, module, symbol)
1428     lt_user_data loader_data;
1429     lt_module module;
1430     const char *symbol;
1431{
1432  lt_ptr      address  = GetProcAddress (module, symbol);
1433
1434  if (!address)
1435    {
1436      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1437    }
1438
1439  return address;
1440}
1441
1442static struct lt_user_dlloader sys_wll = {
1443  0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1444};
1445
1446#endif /* __WINDOWS__ */
1447
1448
1449
1450
1451/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1452
1453
1454#ifdef __BEOS__
1455
1456/* dynamic linking for BeOS */
1457
1458#include <kernel/image.h>
1459
1460static lt_module
1461sys_bedl_open (loader_data, filename)
1462     lt_user_data loader_data;
1463     const char *filename;
1464{
1465  image_id image = 0;
1466
1467  if (filename)
1468    {
1469      image = load_add_on (filename);
1470    }
1471  else
1472    {
1473      image_info info;
1474      int32 cookie = 0;
1475      if (get_next_image_info (0, &cookie, &info) == B_OK)
1476	image = load_add_on (info.name);
1477    }
1478
1479  if (image <= 0)
1480    {
1481      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1482      image = 0;
1483    }
1484
1485  return (lt_module) image;
1486}
1487
1488static int
1489sys_bedl_close (loader_data, module)
1490     lt_user_data loader_data;
1491     lt_module module;
1492{
1493  int errors = 0;
1494
1495  if (unload_add_on ((image_id) module) != B_OK)
1496    {
1497      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1498      ++errors;
1499    }
1500
1501  return errors;
1502}
1503
1504static lt_ptr
1505sys_bedl_sym (loader_data, module, symbol)
1506     lt_user_data loader_data;
1507     lt_module module;
1508     const char *symbol;
1509{
1510  lt_ptr address = 0;
1511  image_id image = (image_id) module;
1512
1513  if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1514    {
1515      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1516      address = 0;
1517    }
1518
1519  return address;
1520}
1521
1522static struct lt_user_dlloader sys_bedl = {
1523  0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1524};
1525
1526#endif /* __BEOS__ */
1527
1528
1529
1530
1531/* --- DLD_LINK() INTERFACE LOADER --- */
1532
1533
1534#if HAVE_DLD
1535
1536/* dynamic linking with dld */
1537
1538#if HAVE_DLD_H
1539#include <dld.h>
1540#endif
1541
1542static lt_module
1543sys_dld_open (loader_data, filename)
1544     lt_user_data loader_data;
1545     const char *filename;
1546{
1547  lt_module module = strdup (filename);
1548
1549  if (dld_link (filename) != 0)
1550    {
1551      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1552      LT_DLFREE (module);
1553      module = 0;
1554    }
1555
1556  return module;
1557}
1558
1559static int
1560sys_dld_close (loader_data, module)
1561     lt_user_data loader_data;
1562     lt_module module;
1563{
1564  int errors = 0;
1565
1566  if (dld_unlink_by_file ((char*)(module), 1) != 0)
1567    {
1568      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1569      ++errors;
1570    }
1571  else
1572    {
1573      LT_DLFREE (module);
1574    }
1575
1576  return errors;
1577}
1578
1579static lt_ptr
1580sys_dld_sym (loader_data, module, symbol)
1581     lt_user_data loader_data;
1582     lt_module module;
1583     const char *symbol;
1584{
1585  lt_ptr address = dld_get_func (symbol);
1586
1587  if (!address)
1588    {
1589      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1590    }
1591
1592  return address;
1593}
1594
1595static struct lt_user_dlloader sys_dld = {
1596  0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1597};
1598
1599#endif /* HAVE_DLD */
1600
1601/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1602#if HAVE_DYLD
1603
1604
1605#if HAVE_MACH_O_DYLD_H
1606#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1607/* Is this correct? Does it still function properly? */
1608#define __private_extern__ extern
1609#endif
1610# include <mach-o/dyld.h>
1611#endif
1612#include <mach-o/getsect.h>
1613
1614/* We have to put some stuff here that isn't in older dyld.h files */
1615#ifndef ENUM_DYLD_BOOL
1616# define ENUM_DYLD_BOOL
1617# undef FALSE
1618# undef TRUE
1619 enum DYLD_BOOL {
1620    FALSE,
1621    TRUE
1622 };
1623#endif
1624#ifndef LC_REQ_DYLD
1625# define LC_REQ_DYLD 0x80000000
1626#endif
1627#ifndef LC_LOAD_WEAK_DYLIB
1628# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1629#endif
1630static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1631static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1632static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1633static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1634
1635#ifndef NSADDIMAGE_OPTION_NONE
1636#define NSADDIMAGE_OPTION_NONE                          0x0
1637#endif
1638#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1639#define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
1640#endif
1641#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1642#define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
1643#endif
1644#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1645#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
1646#endif
1647#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1648#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1649#endif
1650#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1651#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
1652#endif
1653#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1654#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
1655#endif
1656#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1657#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
1658#endif
1659#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1660#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1661#endif
1662
1663
1664static const char *
1665lt_int_dyld_error(othererror)
1666	char* othererror;
1667{
1668/* return the dyld error string, or the passed in error string if none */
1669	NSLinkEditErrors ler;
1670	int lerno;
1671	const char *errstr;
1672	const char *file;
1673	NSLinkEditError(&ler,&lerno,&file,&errstr);
1674	if (!errstr || !strlen(errstr)) errstr = othererror;
1675	return errstr;
1676}
1677
1678static const struct mach_header *
1679lt_int_dyld_get_mach_header_from_nsmodule(module)
1680	NSModule module;
1681{
1682/* There should probably be an apple dyld api for this */
1683	int i=_dyld_image_count();
1684	int j;
1685	const char *modname=NSNameOfModule(module);
1686	const struct mach_header *mh=NULL;
1687	if (!modname) return NULL;
1688	for (j = 0; j < i; j++)
1689	{
1690		if (!strcmp(_dyld_get_image_name(j),modname))
1691		{
1692			mh=_dyld_get_image_header(j);
1693			break;
1694		}
1695	}
1696	return mh;
1697}
1698
1699static const char* lt_int_dyld_lib_install_name(mh)
1700	const struct mach_header *mh;
1701{
1702/* NSAddImage is also used to get the loaded image, but it only works if the lib
1703   is installed, for uninstalled libs we need to check the install_names against
1704   each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1705   different lib was loaded as a result
1706*/
1707	int j;
1708	struct load_command *lc;
1709	unsigned long offset = sizeof(struct mach_header);
1710	const char* retStr=NULL;
1711	for (j = 0; j < mh->ncmds; j++)
1712	{
1713		lc = (struct load_command*)(((unsigned long)mh) + offset);
1714		if (LC_ID_DYLIB == lc->cmd)
1715		{
1716			retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1717									(unsigned long)lc);
1718		}
1719		offset += lc->cmdsize;
1720	}
1721	return retStr;
1722}
1723
1724static const struct mach_header *
1725lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1726{
1727	int i=_dyld_image_count();
1728	int j;
1729	const struct mach_header *mh=NULL;
1730	const char *id=NULL;
1731	for (j = 0; j < i; j++)
1732	{
1733		id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1734		if ((id) && (!strcmp(id,name)))
1735		{
1736			mh=_dyld_get_image_header(j);
1737			break;
1738		}
1739	}
1740	return mh;
1741}
1742
1743static NSSymbol
1744lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1745	const char *symbol;
1746	const struct mach_header *mh;
1747{
1748	/* Safe to assume our mh is good */
1749	int j;
1750	struct load_command *lc;
1751	unsigned long offset = sizeof(struct mach_header);
1752	NSSymbol retSym = 0;
1753	const struct mach_header *mh1;
1754	if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1755	{
1756		for (j = 0; j < mh->ncmds; j++)
1757		{
1758			lc = (struct load_command*)(((unsigned long)mh) + offset);
1759			if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1760			{
1761				mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1762										(unsigned long)lc));
1763				if (!mh1)
1764				{
1765					/* Maybe NSAddImage can find it */
1766					mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1767										(unsigned long)lc),
1768										NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1769										NSADDIMAGE_OPTION_WITH_SEARCHING +
1770										NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1771				}
1772				if (mh1)
1773				{
1774					retSym = ltdl_NSLookupSymbolInImage(mh1,
1775											symbol,
1776											NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1777											| NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1778											);
1779					if (retSym) break;
1780				}
1781			}
1782			offset += lc->cmdsize;
1783		}
1784	}
1785	return retSym;
1786}
1787
1788static int
1789sys_dyld_init()
1790{
1791	int retCode = 0;
1792	int err = 0;
1793	if (!_dyld_present()) {
1794		retCode=1;
1795	}
1796	else {
1797      err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1798      err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1799      err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1800      err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1801    }
1802 return retCode;
1803}
1804
1805static lt_module
1806sys_dyld_open (loader_data, filename)
1807     lt_user_data loader_data;
1808     const char *filename;
1809{
1810	lt_module   module   = 0;
1811	NSObjectFileImage ofi = 0;
1812	NSObjectFileImageReturnCode ofirc;
1813
1814  	if (!filename)
1815  		return (lt_module)-1;
1816	ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1817	switch (ofirc)
1818	{
1819		case NSObjectFileImageSuccess:
1820			module = NSLinkModule(ofi, filename,
1821						NSLINKMODULE_OPTION_RETURN_ON_ERROR
1822						 | NSLINKMODULE_OPTION_PRIVATE
1823						 | NSLINKMODULE_OPTION_BINDNOW);
1824			NSDestroyObjectFileImage(ofi);
1825			if (module)
1826				ltdl_NSMakePrivateModulePublic(module);
1827			break;
1828		case NSObjectFileImageInappropriateFile:
1829		    if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1830		    {
1831				module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1832				break;
1833			}
1834		default:
1835			LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1836			return 0;
1837	}
1838	if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1839  return module;
1840}
1841
1842static int
1843sys_dyld_close (loader_data, module)
1844     lt_user_data loader_data;
1845     lt_module module;
1846{
1847	int retCode = 0;
1848	int flags = 0;
1849	if (module == (lt_module)-1) return 0;
1850#ifdef __BIG_ENDIAN__
1851  	if (((struct mach_header *)module)->magic == MH_MAGIC)
1852#else
1853    if (((struct mach_header *)module)->magic == MH_CIGAM)
1854#endif
1855	{
1856	  LT_DLMUTEX_SETERROR("Can not close a dylib");
1857	  retCode = 1;
1858	}
1859	else
1860	{
1861#if 1
1862/* Currently, if a module contains c++ static destructors and it is unloaded, we
1863   get a segfault in atexit(), due to compiler and dynamic loader differences of
1864   opinion, this works around that.
1865*/
1866		if ((const struct section *)NULL !=
1867		   getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1868		   "__DATA","__mod_term_func"))
1869		{
1870			flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1871		}
1872#endif
1873#ifdef __ppc__
1874			flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1875#endif
1876		if (!NSUnLinkModule(module,flags))
1877		{
1878			retCode=1;
1879			LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1880		}
1881	}
1882
1883 return retCode;
1884}
1885
1886static lt_ptr
1887sys_dyld_sym (loader_data, module, symbol)
1888     lt_user_data loader_data;
1889     lt_module module;
1890     const char *symbol;
1891{
1892	lt_ptr address = 0;
1893  	NSSymbol *nssym = 0;
1894  	void *unused;
1895  	const struct mach_header *mh=NULL;
1896  	char saveError[256] = "Symbol not found";
1897  	if (module == (lt_module)-1)
1898  	{
1899  		_dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1900  		return address;
1901  	}
1902#ifdef __BIG_ENDIAN__
1903  	if (((struct mach_header *)module)->magic == MH_MAGIC)
1904#else
1905    if (((struct mach_header *)module)->magic == MH_CIGAM)
1906#endif
1907  	{
1908  	    if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1909  	    {
1910  	    	mh=module;
1911			if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1912			{
1913				nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1914											symbol,
1915											NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1916											| NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1917											);
1918			}
1919	    }
1920
1921  	}
1922  else {
1923	nssym = NSLookupSymbolInModule(module, symbol);
1924	}
1925	if (!nssym)
1926	{
1927		strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1928		saveError[255] = 0;
1929		if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1930		nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1931	}
1932	if (!nssym)
1933	{
1934		LT_DLMUTEX_SETERROR (saveError);
1935		return NULL;
1936	}
1937	return NSAddressOfSymbol(nssym);
1938}
1939
1940static struct lt_user_dlloader sys_dyld =
1941  { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1942
1943
1944#endif /* HAVE_DYLD */
1945
1946
1947/* --- DLPREOPEN() INTERFACE LOADER --- */
1948
1949
1950/* emulate dynamic linking using preloaded_symbols */
1951
1952typedef struct lt_dlsymlists_t
1953{
1954  struct lt_dlsymlists_t       *next;
1955  const lt_dlsymlist	       *syms;
1956} lt_dlsymlists_t;
1957
1958static	const lt_dlsymlist     *default_preloaded_symbols	= 0;
1959static	lt_dlsymlists_t	       *preloaded_symbols		= 0;
1960
1961static int
1962presym_init (loader_data)
1963     lt_user_data loader_data;
1964{
1965  int errors = 0;
1966
1967  LT_DLMUTEX_LOCK ();
1968
1969  preloaded_symbols = 0;
1970  if (default_preloaded_symbols)
1971    {
1972      errors = lt_dlpreload (default_preloaded_symbols);
1973    }
1974
1975  LT_DLMUTEX_UNLOCK ();
1976
1977  return errors;
1978}
1979
1980static int
1981presym_free_symlists ()
1982{
1983  lt_dlsymlists_t *lists;
1984
1985  LT_DLMUTEX_LOCK ();
1986
1987  lists = preloaded_symbols;
1988  while (lists)
1989    {
1990      lt_dlsymlists_t	*tmp = lists;
1991
1992      lists = lists->next;
1993      LT_DLFREE (tmp);
1994    }
1995  preloaded_symbols = 0;
1996
1997  LT_DLMUTEX_UNLOCK ();
1998
1999  return 0;
2000}
2001
2002static int
2003presym_exit (loader_data)
2004     lt_user_data loader_data;
2005{
2006  presym_free_symlists ();
2007  return 0;
2008}
2009
2010static int
2011presym_add_symlist (preloaded)
2012     const lt_dlsymlist *preloaded;
2013{
2014  lt_dlsymlists_t *tmp;
2015  lt_dlsymlists_t *lists;
2016  int		   errors   = 0;
2017
2018  LT_DLMUTEX_LOCK ();
2019
2020  lists = preloaded_symbols;
2021  while (lists)
2022    {
2023      if (lists->syms == preloaded)
2024	{
2025	  goto done;
2026	}
2027      lists = lists->next;
2028    }
2029
2030  tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2031  if (tmp)
2032    {
2033      memset (tmp, 0, sizeof(lt_dlsymlists_t));
2034      tmp->syms = preloaded;
2035      tmp->next = preloaded_symbols;
2036      preloaded_symbols = tmp;
2037    }
2038  else
2039    {
2040      ++errors;
2041    }
2042
2043 done:
2044  LT_DLMUTEX_UNLOCK ();
2045  return errors;
2046}
2047
2048static lt_module
2049presym_open (loader_data, filename)
2050     lt_user_data loader_data;
2051     const char *filename;
2052{
2053  lt_dlsymlists_t *lists;
2054  lt_module	   module = (lt_module) 0;
2055
2056  LT_DLMUTEX_LOCK ();
2057  lists = preloaded_symbols;
2058
2059  if (!lists)
2060    {
2061      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2062      goto done;
2063    }
2064
2065  /* Can't use NULL as the reflective symbol header, as NULL is
2066     used to mark the end of the entire symbol list.  Self-dlpreopened
2067     symbols follow this magic number, chosen to be an unlikely
2068     clash with a real module name.  */
2069  if (!filename)
2070    {
2071      filename = "@PROGRAM@";
2072    }
2073
2074  while (lists)
2075    {
2076      const lt_dlsymlist *syms = lists->syms;
2077
2078      while (syms->name)
2079	{
2080	  if (!syms->address && strcmp(syms->name, filename) == 0)
2081	    {
2082	      module = (lt_module) syms;
2083	      goto done;
2084	    }
2085	  ++syms;
2086	}
2087
2088      lists = lists->next;
2089    }
2090
2091  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2092
2093 done:
2094  LT_DLMUTEX_UNLOCK ();
2095  return module;
2096}
2097
2098static int
2099presym_close (loader_data, module)
2100     lt_user_data loader_data;
2101     lt_module module;
2102{
2103  /* Just to silence gcc -Wall */
2104  module = 0;
2105  return 0;
2106}
2107
2108static lt_ptr
2109presym_sym (loader_data, module, symbol)
2110     lt_user_data loader_data;
2111     lt_module module;
2112     const char *symbol;
2113{
2114  lt_dlsymlist *syms = (lt_dlsymlist*) module;
2115
2116  ++syms;
2117  while (syms->address)
2118    {
2119      if (strcmp(syms->name, symbol) == 0)
2120	{
2121	  return syms->address;
2122	}
2123
2124    ++syms;
2125  }
2126
2127  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2128
2129  return 0;
2130}
2131
2132static struct lt_user_dlloader presym = {
2133  0, presym_open, presym_close, presym_sym, presym_exit, 0
2134};
2135
2136
2137
2138
2139
2140/* --- DYNAMIC MODULE LOADING --- */
2141
2142
2143/* The type of a function used at each iteration of  foreach_dirinpath().  */
2144typedef int	foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2145						 lt_ptr data2));
2146
2147static	int	foreach_dirinpath     LT_PARAMS((const char *search_path,
2148						 const char *base_name,
2149						 foreach_callback_func *func,
2150						 lt_ptr data1, lt_ptr data2));
2151
2152static	int	find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
2153						 lt_ptr ignored));
2154static	int	find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
2155						 lt_ptr ignored));
2156static	int	foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
2157						 lt_ptr data2));
2158
2159
2160static	int     canonicalize_path     LT_PARAMS((const char *path,
2161						 char **pcanonical));
2162static	int	argzize_path 	      LT_PARAMS((const char *path,
2163						 char **pargz,
2164						 size_t *pargz_len));
2165static	FILE   *find_file	      LT_PARAMS((const char *search_path,
2166						 const char *base_name,
2167						 char **pdir));
2168static	lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
2169						 const char *base_name,
2170						 lt_dlhandle *handle));
2171static	int	find_module	      LT_PARAMS((lt_dlhandle *handle,
2172						 const char *dir,
2173						 const char *libdir,
2174						 const char *dlname,
2175						 const char *old_name,
2176						 int installed));
2177static	int	free_vars	      LT_PARAMS((char *dlname, char *oldname,
2178						 char *libdir, char *deplibs));
2179static	int	load_deplibs	      LT_PARAMS((lt_dlhandle handle,
2180						 char *deplibs));
2181s

Large files files are truncated, but you can click here to view the full file