~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to lib/libLtdl/ltdl.c

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2009-09-24 14:51:06 UTC
  • mfrom: (1.1.12 upstream)
  • mto: (20.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20090924145106-38jgrzmj0d73pha5
Tags: 3.1.0.13-1
* Upload to experimental

* New upstream release
  - Fixes Follow-X-Forwarded-For support (Closes: #523943)
  - Adds IPv6 support (Closes: #432351)

* debian/rules
  - Removed obsolete configuration options
  - Enable db and radius basic authentication modules

* debian/patches/01-cf.data.debian
  - Adapted to new upstream version

* debian/patches/02-makefile-defaults
  - Adapted to new upstream version

* debian/{squid.postinst,squid.rc,README.Debian,watch}
  - Updated references to squid 3.1

* debian/squid3.install
  - Install CSS file for error pages
  - Install manual pages for new authentication modules

* debian/squid3-common.install
  - Install documented version of configuration file in /usr/share/doc/squid3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ltdl.c -- system independent dlopen wrapper
 
2
   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
3
   Originally by Thomas Tanner <tanner@ffii.org>
 
4
   This file is part of GNU Libtool.
 
5
 
 
6
This library is free software; you can redistribute it and/or
 
7
modify it under the terms of the GNU Lesser General Public
 
8
License as published by the Free Software Foundation; either
 
9
version 2 of the License, or (at your option) any later version.
 
10
 
 
11
As a special exception to the GNU Lesser General Public License,
 
12
if you distribute this file as part of a program or library that
 
13
is built using GNU libtool, you may include it under the same
 
14
distribution terms that you use for the rest of that program.
 
15
 
 
16
This library is distributed in the hope that it will be useful,
 
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
19
Lesser General Public License for more details.
 
20
 
 
21
You should have received a copy of the GNU Lesser General Public
 
22
License along with this library; if not, write to the Free Software
 
23
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
24
02110-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
/* DLL building support on win32 hosts;  mostly to workaround their
 
141
   ridiculous implementation of data symbol exporting. */
 
142
#ifndef LT_GLOBAL_DATA
 
143
#  if defined(__WINDOWS__) || defined(__CYGWIN__)
 
144
#    ifdef DLL_EXPORT           /* defined by libtool (if required) */
 
145
#      define LT_GLOBAL_DATA __declspec(dllexport)
 
146
#    endif
 
147
#  endif
 
148
#  ifndef LT_GLOBAL_DATA        /* static linking or !__WINDOWS__ */
 
149
#    define LT_GLOBAL_DATA
 
150
#  endif
 
151
#endif
 
152
 
 
153
/* fopen() mode flags for reading a text file */
 
154
#undef  LT_READTEXT_MODE
 
155
#if defined(__WINDOWS__) || defined(__CYGWIN__)
 
156
#  define LT_READTEXT_MODE "rt"
 
157
#else
 
158
#  define LT_READTEXT_MODE "r"
 
159
#endif
 
160
 
 
161
#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
 
162
 
 
163
#include <windows.h>
 
164
 
 
165
#define dirent lt_dirent
 
166
#define DIR lt_DIR
 
167
 
 
168
struct dirent
 
169
{
 
170
  char d_name[2048];
 
171
  int  d_namlen;
 
172
};
 
173
 
 
174
typedef struct _DIR
 
175
{
 
176
  HANDLE hSearch;
 
177
  WIN32_FIND_DATA Win32FindData;
 
178
  BOOL firsttime;
 
179
  struct dirent file_info;
 
180
} DIR;
 
181
 
 
182
#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
 
183
 
 
184
 
 
185
/* --- MANIFEST CONSTANTS --- */
 
186
 
 
187
 
 
188
/* Standard libltdl search path environment variable name  */
 
189
#undef  LTDL_SEARCHPATH_VAR
 
190
#define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
 
191
 
 
192
/* Standard libtool archive file extension.  */
 
193
#undef  LTDL_ARCHIVE_EXT
 
194
#define LTDL_ARCHIVE_EXT        ".la"
 
195
 
 
196
/* max. filename length */
 
197
#ifndef LT_FILENAME_MAX
 
198
#  define LT_FILENAME_MAX       1024
 
199
#endif
 
200
 
 
201
/* This is the maximum symbol size that won't require malloc/free */
 
202
#undef  LT_SYMBOL_LENGTH
 
203
#define LT_SYMBOL_LENGTH        128
 
204
 
 
205
/* This accounts for the _LTX_ separator */
 
206
#undef  LT_SYMBOL_OVERHEAD
 
207
#define LT_SYMBOL_OVERHEAD      5
 
208
 
 
209
 
 
210
 
 
211
 
 
212
/* --- MEMORY HANDLING --- */
 
213
 
 
214
 
 
215
/* These are the functions used internally.  In addition to making
 
216
   use of the associated function pointers above, they also perform
 
217
   error handling.  */
 
218
static char   *lt_estrdup       LT_PARAMS((const char *str));
 
219
static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
 
220
static lt_ptr lt_erealloc       LT_PARAMS((lt_ptr addr, size_t size));
 
221
 
 
222
/* static lt_ptr rpl_realloc    LT_PARAMS((lt_ptr ptr, size_t size)); */
 
223
#define rpl_realloc realloc
 
224
 
 
225
/* These are the pointers that can be changed by the caller:  */
 
226
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
 
227
                        = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
 
228
LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)   LT_PARAMS((lt_ptr ptr, size_t size))
 
229
                        = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
 
230
LT_GLOBAL_DATA void   (*lt_dlfree)      LT_PARAMS((lt_ptr ptr))
 
231
                        = (void (*) LT_PARAMS((lt_ptr))) free;
 
232
 
 
233
/* The following macros reduce the amount of typing needed to cast
 
234
   assigned memory.  */
 
235
#if WITH_DMALLOC
 
236
 
 
237
#define LT_DLMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
 
238
#define LT_DLREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
 
239
#define LT_DLFREE(p)                                            \
 
240
        LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
 
241
 
 
242
#define LT_EMALLOC(tp, n)       ((tp *) xmalloc ((n) * sizeof(tp)))
 
243
#define LT_EREALLOC(tp, p, n)   ((tp *) xrealloc ((p), (n) * sizeof(tp)))
 
244
 
 
245
#else
 
246
 
 
247
#define LT_DLMALLOC(tp, n)      ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
 
248
#define LT_DLREALLOC(tp, p, n)  ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
 
249
#define LT_DLFREE(p)                                            \
 
250
        LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
 
251
 
 
252
#define LT_EMALLOC(tp, n)       ((tp *) lt_emalloc ((n) * sizeof(tp)))
 
253
#define LT_EREALLOC(tp, p, n)   ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
 
254
 
 
255
#endif
 
256
 
 
257
#define LT_DLMEM_REASSIGN(p, q)                 LT_STMT_START { \
 
258
        if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
 
259
                                                } LT_STMT_END
 
260
 
 
261
 
 
262
/* --- REPLACEMENT FUNCTIONS --- */
 
263
 
 
264
 
 
265
#undef strdup
 
266
#define strdup rpl_strdup
 
267
 
 
268
static char *strdup LT_PARAMS((const char *str));
 
269
 
 
270
static char *
 
271
strdup(str)
 
272
     const char *str;
 
273
{
 
274
  char *tmp = 0;
 
275
 
 
276
  if (str)
 
277
    {
 
278
      tmp = LT_DLMALLOC (char, 1+ strlen (str));
 
279
      if (tmp)
 
280
        {
 
281
          strcpy(tmp, str);
 
282
        }
 
283
    }
 
284
 
 
285
  return tmp;
 
286
}
 
287
 
 
288
 
 
289
#if ! HAVE_STRCMP
 
290
 
 
291
#undef strcmp
 
292
#define strcmp rpl_strcmp
 
293
 
 
294
static int strcmp LT_PARAMS((const char *str1, const char *str2));
 
295
 
 
296
static int
 
297
strcmp (str1, str2)
 
298
     const char *str1;
 
299
     const char *str2;
 
300
{
 
301
  if (str1 == str2)
 
302
    return 0;
 
303
  if (str1 == 0)
 
304
    return -1;
 
305
  if (str2 == 0)
 
306
    return 1;
 
307
 
 
308
  for (;*str1 && *str2; ++str1, ++str2)
 
309
    {
 
310
      if (*str1 != *str2)
 
311
        break;
 
312
    }
 
313
 
 
314
  return (int)(*str1 - *str2);
 
315
}
 
316
#endif
 
317
 
 
318
 
 
319
#if ! HAVE_STRCHR
 
320
 
 
321
#  if HAVE_INDEX
 
322
#    define strchr index
 
323
#  else
 
324
#    define strchr rpl_strchr
 
325
 
 
326
static const char *strchr LT_PARAMS((const char *str, int ch));
 
327
 
 
328
static const char*
 
329
strchr(str, ch)
 
330
     const char *str;
 
331
     int ch;
 
332
{
 
333
  const char *p;
 
334
 
 
335
  for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
 
336
    /*NOWORK*/;
 
337
 
 
338
  return (*p == (char)ch) ? p : 0;
 
339
}
 
340
 
 
341
#  endif
 
342
#endif /* !HAVE_STRCHR */
 
343
 
 
344
 
 
345
#if ! HAVE_STRRCHR
 
346
 
 
347
#  if HAVE_RINDEX
 
348
#    define strrchr rindex
 
349
#  else
 
350
#    define strrchr rpl_strrchr
 
351
 
 
352
static const char *strrchr LT_PARAMS((const char *str, int ch));
 
353
 
 
354
static const char*
 
355
strrchr(str, ch)
 
356
     const char *str;
 
357
     int ch;
 
358
{
 
359
  const char *p, *q = 0;
 
360
 
 
361
  for (p = str; *p != LT_EOS_CHAR; ++p)
 
362
    {
 
363
      if (*p == (char) ch)
 
364
        {
 
365
          q = p;
 
366
        }
 
367
    }
 
368
 
 
369
  return q;
 
370
}
 
371
 
 
372
# endif
 
373
#endif
 
374
 
 
375
/* NOTE:  Neither bcopy nor the memcpy implementation below can
 
376
          reliably handle copying in overlapping areas of memory.  Use
 
377
          memmove (for which there is a fallback implmentation below)
 
378
          if you need that behaviour.  */
 
379
#if ! HAVE_MEMCPY
 
380
 
 
381
#  if HAVE_BCOPY
 
382
#    define memcpy(dest, src, size)     bcopy (src, dest, size)
 
383
#  else
 
384
#    define memcpy rpl_memcpy
 
385
 
 
386
static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
 
387
 
 
388
static lt_ptr
 
389
memcpy (dest, src, size)
 
390
     lt_ptr dest;
 
391
     const lt_ptr src;
 
392
     size_t size;
 
393
{
 
394
  const char *  s = src;
 
395
  char *        d = dest;
 
396
  size_t        i = 0;
 
397
 
 
398
  for (i = 0; i < size; ++i)
 
399
    {
 
400
      d[i] = s[i];
 
401
    }
 
402
 
 
403
  return dest;
 
404
}
 
405
 
 
406
#  endif /* !HAVE_BCOPY */
 
407
#endif   /* !HAVE_MEMCPY */
 
408
 
 
409
#if ! HAVE_MEMMOVE
 
410
#  define memmove rpl_memmove
 
411
 
 
412
static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
 
413
 
 
414
static lt_ptr
 
415
memmove (dest, src, size)
 
416
     lt_ptr dest;
 
417
     const lt_ptr src;
 
418
     size_t size;
 
419
{
 
420
  const char *  s = src;
 
421
  char *        d = dest;
 
422
  size_t        i;
 
423
 
 
424
  if (d < s)
 
425
    for (i = 0; i < size; ++i)
 
426
      {
 
427
        d[i] = s[i];
 
428
      }
 
429
  else if (d > s && size > 0)
 
430
    for (i = size -1; ; --i)
 
431
      {
 
432
        d[i] = s[i];
 
433
        if (i == 0)
 
434
          break;
 
435
      }
 
436
 
 
437
  return dest;
 
438
}
 
439
 
 
440
#endif /* !HAVE_MEMMOVE */
 
441
 
 
442
#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
 
443
 
 
444
static void closedir LT_PARAMS((DIR *entry));
 
445
 
 
446
static void
 
447
closedir(entry)
 
448
  DIR *entry;
 
449
{
 
450
  assert(entry != (DIR *) NULL);
 
451
  FindClose(entry->hSearch);
 
452
  lt_dlfree((lt_ptr)entry);
 
453
}
 
454
 
 
455
 
 
456
static DIR * opendir LT_PARAMS((const char *path));
 
457
 
 
458
static DIR*
 
459
opendir (path)
 
460
  const char *path;
 
461
{
 
462
  char file_specification[LT_FILENAME_MAX];
 
463
  DIR *entry;
 
464
 
 
465
  assert(path != (char *) NULL);
 
466
  /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
 
467
  (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
 
468
  file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
 
469
  (void) strcat(file_specification,"\\");
 
470
  entry = LT_DLMALLOC (DIR,sizeof(DIR));
 
471
  if (entry != (DIR *) 0)
 
472
    {
 
473
      entry->firsttime = TRUE;
 
474
      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
 
475
    }
 
476
  if (entry->hSearch == INVALID_HANDLE_VALUE)
 
477
    {
 
478
      (void) strcat(file_specification,"\\*.*");
 
479
      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
 
480
      if (entry->hSearch == INVALID_HANDLE_VALUE)
 
481
        {
 
482
          LT_DLFREE (entry);
 
483
          return (DIR *) 0;
 
484
        }
 
485
    }
 
486
  return(entry);
 
487
}
 
488
 
 
489
 
 
490
static struct dirent *readdir LT_PARAMS((DIR *entry));
 
491
 
 
492
static struct dirent *readdir(entry)
 
493
  DIR *entry;
 
494
{
 
495
  int
 
496
    status;
 
497
 
 
498
  if (entry == (DIR *) 0)
 
499
    return((struct dirent *) 0);
 
500
  if (!entry->firsttime)
 
501
    {
 
502
      status = FindNextFile(entry->hSearch,&entry->Win32FindData);
 
503
      if (status == 0)
 
504
        return((struct dirent *) 0);
 
505
    }
 
506
  entry->firsttime = FALSE;
 
507
  (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
 
508
    LT_FILENAME_MAX-1);
 
509
  entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
 
510
  entry->file_info.d_namlen = strlen(entry->file_info.d_name);
 
511
  return(&entry->file_info);
 
512
}
 
513
 
 
514
#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
 
515
 
 
516
/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
 
517
    ``realloc is not entirely portable''
 
518
   In any case we want to use the allocator supplied by the user without
 
519
   burdening them with an lt_dlrealloc function pointer to maintain.
 
520
   Instead implement our own version (with known boundary conditions)
 
521
   using lt_dlmalloc and lt_dlfree. */
 
522
 
 
523
/* #undef realloc
 
524
   #define realloc rpl_realloc
 
525
*/
 
526
#if 0
 
527
  /* You can't (re)define realloc unless you also (re)define malloc.
 
528
     Right now, this code uses the size of the *destination* to decide
 
529
     how much to copy.  That's not right, but you can't know the size
 
530
     of the source unless you know enough about, or wrote malloc.  So
 
531
     this code is disabled... */
 
532
 
 
533
static lt_ptr
 
534
realloc (ptr, size)
 
535
     lt_ptr ptr;
 
536
     size_t size;
 
537
{
 
538
  if (size == 0)
 
539
    {
 
540
      /* For zero or less bytes, free the original memory */
 
541
      if (ptr != 0)
 
542
        {
 
543
          lt_dlfree (ptr);
 
544
        }
 
545
 
 
546
      return (lt_ptr) 0;
 
547
    }
 
548
  else if (ptr == 0)
 
549
    {
 
550
      /* Allow reallocation of a NULL pointer.  */
 
551
      return lt_dlmalloc (size);
 
552
    }
 
553
  else
 
554
    {
 
555
      /* Allocate a new block, copy and free the old block.  */
 
556
      lt_ptr mem = lt_dlmalloc (size);
 
557
 
 
558
      if (mem)
 
559
        {
 
560
          memcpy (mem, ptr, size);
 
561
          lt_dlfree (ptr);
 
562
        }
 
563
 
 
564
      /* Note that the contents of PTR are not damaged if there is
 
565
         insufficient memory to realloc.  */
 
566
      return mem;
 
567
    }
 
568
}
 
569
#endif
 
570
 
 
571
 
 
572
#if ! HAVE_ARGZ_APPEND
 
573
#  define argz_append rpl_argz_append
 
574
 
 
575
static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
 
576
                                        const char *buf, size_t buf_len));
 
577
 
 
578
static error_t
 
579
argz_append (pargz, pargz_len, buf, buf_len)
 
580
     char **pargz;
 
581
     size_t *pargz_len;
 
582
     const char *buf;
 
583
     size_t buf_len;
 
584
{
 
585
  size_t argz_len;
 
586
  char  *argz;
 
587
 
 
588
  assert (pargz);
 
589
  assert (pargz_len);
 
590
  assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
 
591
 
 
592
  /* If nothing needs to be appended, no more work is required.  */
 
593
  if (buf_len == 0)
 
594
    return 0;
 
595
 
 
596
  /* Ensure there is enough room to append BUF_LEN.  */
 
597
  argz_len = *pargz_len + buf_len;
 
598
  argz = LT_DLREALLOC (char, *pargz, argz_len);
 
599
  if (!argz)
 
600
    return ENOMEM;
 
601
 
 
602
  /* Copy characters from BUF after terminating '\0' in ARGZ.  */
 
603
  memcpy (argz + *pargz_len, buf, buf_len);
 
604
 
 
605
  /* Assign new values.  */
 
606
  *pargz = argz;
 
607
  *pargz_len = argz_len;
 
608
 
 
609
  return 0;
 
610
}
 
611
#endif /* !HAVE_ARGZ_APPEND */
 
612
 
 
613
 
 
614
#if ! HAVE_ARGZ_CREATE_SEP
 
615
#  define argz_create_sep rpl_argz_create_sep
 
616
 
 
617
static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
 
618
                                            char **pargz, size_t *pargz_len));
 
619
 
 
620
static error_t
 
621
argz_create_sep (str, delim, pargz, pargz_len)
 
622
     const char *str;
 
623
     int delim;
 
624
     char **pargz;
 
625
     size_t *pargz_len;
 
626
{
 
627
  size_t argz_len;
 
628
  char *argz = 0;
 
629
 
 
630
  assert (str);
 
631
  assert (pargz);
 
632
  assert (pargz_len);
 
633
 
 
634
  /* Make a copy of STR, but replacing each occurrence of
 
635
     DELIM with '\0'.  */
 
636
  argz_len = 1+ LT_STRLEN (str);
 
637
  if (argz_len)
 
638
    {
 
639
      const char *p;
 
640
      char *q;
 
641
 
 
642
      argz = LT_DLMALLOC (char, argz_len);
 
643
      if (!argz)
 
644
        return ENOMEM;
 
645
 
 
646
      for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
 
647
        {
 
648
          if (*p == delim)
 
649
            {
 
650
              /* Ignore leading delimiters, and fold consecutive
 
651
                 delimiters in STR into a single '\0' in ARGZ.  */
 
652
              if ((q > argz) && (q[-1] != LT_EOS_CHAR))
 
653
                *q++ = LT_EOS_CHAR;
 
654
              else
 
655
                --argz_len;
 
656
            }
 
657
          else
 
658
            *q++ = *p;
 
659
        }
 
660
      /* Copy terminating LT_EOS_CHAR.  */
 
661
      *q = *p;
 
662
    }
 
663
 
 
664
  /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
 
665
  if (!argz_len)
 
666
    LT_DLFREE (argz);
 
667
 
 
668
  /* Assign new values.  */
 
669
  *pargz = argz;
 
670
  *pargz_len = argz_len;
 
671
 
 
672
  return 0;
 
673
}
 
674
#endif /* !HAVE_ARGZ_CREATE_SEP */
 
675
 
 
676
 
 
677
#if ! HAVE_ARGZ_INSERT
 
678
#  define argz_insert rpl_argz_insert
 
679
 
 
680
static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
 
681
                                        char *before, const char *entry));
 
682
 
 
683
static error_t
 
684
argz_insert (pargz, pargz_len, before, entry)
 
685
     char **pargz;
 
686
     size_t *pargz_len;
 
687
     char *before;
 
688
     const char *entry;
 
689
{
 
690
  assert (pargz);
 
691
  assert (pargz_len);
 
692
  assert (entry && *entry);
 
693
 
 
694
  /* No BEFORE address indicates ENTRY should be inserted after the
 
695
     current last element.  */
 
696
  if (!before)
 
697
    return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
 
698
 
 
699
  /* This probably indicates a programmer error, but to preserve
 
700
     semantics, scan back to the start of an entry if BEFORE points
 
701
     into the middle of it.  */
 
702
  while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
 
703
    --before;
 
704
 
 
705
  {
 
706
    size_t entry_len    = 1+ LT_STRLEN (entry);
 
707
    size_t argz_len     = *pargz_len + entry_len;
 
708
    size_t offset       = before - *pargz;
 
709
    char   *argz        = LT_DLREALLOC (char, *pargz, argz_len);
 
710
 
 
711
    if (!argz)
 
712
      return ENOMEM;
 
713
 
 
714
    /* Make BEFORE point to the equivalent offset in ARGZ that it
 
715
       used to have in *PARGZ incase realloc() moved the block.  */
 
716
    before = argz + offset;
 
717
 
 
718
    /* Move the ARGZ entries starting at BEFORE up into the new
 
719
       space at the end -- making room to copy ENTRY into the
 
720
       resulting gap.  */
 
721
    memmove (before + entry_len, before, *pargz_len - offset);
 
722
    memcpy  (before, entry, entry_len);
 
723
 
 
724
    /* Assign new values.  */
 
725
    *pargz = argz;
 
726
    *pargz_len = argz_len;
 
727
  }
 
728
 
 
729
  return 0;
 
730
}
 
731
#endif /* !HAVE_ARGZ_INSERT */
 
732
 
 
733
 
 
734
#if ! HAVE_ARGZ_NEXT
 
735
#  define argz_next rpl_argz_next
 
736
 
 
737
static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
 
738
                                    const char *entry));
 
739
 
 
740
static char *
 
741
argz_next (argz, argz_len, entry)
 
742
     char *argz;
 
743
     size_t argz_len;
 
744
     const char *entry;
 
745
{
 
746
  assert ((argz && argz_len) || (!argz && !argz_len));
 
747
 
 
748
  if (entry)
 
749
    {
 
750
      /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
 
751
         within the ARGZ vector.  */
 
752
      assert ((!argz && !argz_len)
 
753
              || ((argz <= entry) && (entry < (argz + argz_len))));
 
754
 
 
755
      /* Move to the char immediately after the terminating
 
756
         '\0' of ENTRY.  */
 
757
      entry = 1+ strchr (entry, LT_EOS_CHAR);
 
758
 
 
759
      /* Return either the new ENTRY, or else NULL if ARGZ is
 
760
         exhausted.  */
 
761
      return (entry >= argz + argz_len) ? 0 : (char *) entry;
 
762
    }
 
763
  else
 
764
    {
 
765
      /* This should probably be flagged as a programmer error,
 
766
         since starting an argz_next loop with the iterator set
 
767
         to ARGZ is safer.  To preserve semantics, handle the NULL
 
768
         case by returning the start of ARGZ (if any).  */
 
769
      if (argz_len > 0)
 
770
        return argz;
 
771
      else
 
772
        return 0;
 
773
    }
 
774
}
 
775
#endif /* !HAVE_ARGZ_NEXT */
 
776
 
 
777
 
 
778
 
 
779
#if ! HAVE_ARGZ_STRINGIFY
 
780
#  define argz_stringify rpl_argz_stringify
 
781
 
 
782
static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
 
783
                                       int sep));
 
784
 
 
785
static void
 
786
argz_stringify (argz, argz_len, sep)
 
787
     char *argz;
 
788
     size_t argz_len;
 
789
     int sep;
 
790
{
 
791
  assert ((argz && argz_len) || (!argz && !argz_len));
 
792
 
 
793
  if (sep)
 
794
    {
 
795
      --argz_len;               /* don't stringify the terminating EOS */
 
796
      while (--argz_len > 0)
 
797
        {
 
798
          if (argz[argz_len] == LT_EOS_CHAR)
 
799
            argz[argz_len] = sep;
 
800
        }
 
801
    }
 
802
}
 
803
#endif /* !HAVE_ARGZ_STRINGIFY */
 
804
 
 
805
 
 
806
 
 
807
 
 
808
/* --- TYPE DEFINITIONS -- */
 
809
 
 
810
 
 
811
/* This type is used for the array of caller data sets in each handler. */
 
812
typedef struct {
 
813
  lt_dlcaller_id        key;
 
814
  lt_ptr                data;
 
815
} lt_caller_data;
 
816
 
 
817
 
 
818
 
 
819
 
 
820
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
 
821
 
 
822
 
 
823
/* Extract the diagnostic strings from the error table macro in the same
 
824
   order as the enumerated indices in ltdl.h. */
 
825
 
 
826
static const char *lt_dlerror_strings[] =
 
827
  {
 
828
#define LT_ERROR(name, diagnostic)      (diagnostic),
 
829
    lt_dlerror_table
 
830
#undef LT_ERROR
 
831
 
 
832
    0
 
833
  };
 
834
 
 
835
/* This structure is used for the list of registered loaders. */
 
836
struct lt_dlloader {
 
837
  struct lt_dlloader   *next;
 
838
  const char           *loader_name;    /* identifying name for each loader */
 
839
  const char           *sym_prefix;     /* prefix for symbols */
 
840
  lt_module_open       *module_open;
 
841
  lt_module_close      *module_close;
 
842
  lt_find_sym          *find_sym;
 
843
  lt_dlloader_exit     *dlloader_exit;
 
844
  lt_user_data          dlloader_data;
 
845
};
 
846
 
 
847
struct lt_dlhandle_struct {
 
848
  struct lt_dlhandle_struct   *next;
 
849
  lt_dlloader          *loader;         /* dlopening interface */
 
850
  lt_dlinfo             info;
 
851
  int                   depcount;       /* number of dependencies */
 
852
  lt_dlhandle          *deplibs;        /* dependencies */
 
853
  lt_module             module;         /* system module handle */
 
854
  lt_ptr                system;         /* system specific data */
 
855
  lt_caller_data       *caller_data;    /* per caller associated data */
 
856
  int                   flags;          /* various boolean stats */
 
857
};
 
858
 
 
859
/* Various boolean flags can be stored in the flags field of an
 
860
   lt_dlhandle_struct... */
 
861
#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
 
862
#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
 
863
 
 
864
#define LT_DLRESIDENT_FLAG          (0x01 << 0)
 
865
/* ...add more flags here... */
 
866
 
 
867
#define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
 
868
 
 
869
 
 
870
#define LT_DLSTRERROR(name)     lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
 
871
 
 
872
static  const char      objdir[]                = LTDL_OBJDIR;
 
873
static  const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
 
874
#ifdef  LTDL_SHLIB_EXT
 
875
static  const char      shlib_ext[]             = LTDL_SHLIB_EXT;
 
876
#endif
 
877
#ifdef  LTDL_SYSSEARCHPATH
 
878
static  const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
 
879
#endif
 
880
 
 
881
 
 
882
 
 
883
 
 
884
/* --- MUTEX LOCKING --- */
 
885
 
 
886
 
 
887
/* Macros to make it easier to run the lock functions only if they have
 
888
   been registered.  The reason for the complicated lock macro is to
 
889
   ensure that the stored error message from the last error is not
 
890
   accidentally erased if the current function doesn't generate an
 
891
   error of its own.  */
 
892
#define LT_DLMUTEX_LOCK()                       LT_STMT_START { \
 
893
        if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
 
894
                                                } LT_STMT_END
 
895
#define LT_DLMUTEX_UNLOCK()                     LT_STMT_START { \
 
896
        if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
 
897
                                                } LT_STMT_END
 
898
#define LT_DLMUTEX_SETERROR(errormsg)           LT_STMT_START { \
 
899
        if (lt_dlmutex_seterror_func)                           \
 
900
                (*lt_dlmutex_seterror_func) (errormsg);         \
 
901
        else    lt_dllast_error = (errormsg);   } LT_STMT_END
 
902
#define LT_DLMUTEX_GETERROR(errormsg)           LT_STMT_START { \
 
903
        if (lt_dlmutex_geterror_func)                           \
 
904
                (errormsg) = (*lt_dlmutex_geterror_func) ();    \
 
905
        else    (errormsg) = lt_dllast_error;   } LT_STMT_END
 
906
 
 
907
/* The mutex functions stored here are global, and are necessarily the
 
908
   same for all threads that wish to share access to libltdl.  */
 
909
static  lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
 
910
static  lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
 
911
static  lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
 
912
static  lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
 
913
static  const char          *lt_dllast_error          = 0;
 
914
 
 
915
 
 
916
/* Either set or reset the mutex functions.  Either all the arguments must
 
917
   be valid functions, or else all can be NULL to turn off locking entirely.
 
918
   The registered functions should be manipulating a static global lock
 
919
   from the lock() and unlock() callbacks, which needs to be reentrant.  */
 
920
int
 
921
lt_dlmutex_register (lock, unlock, seterror, geterror)
 
922
     lt_dlmutex_lock *lock;
 
923
     lt_dlmutex_unlock *unlock;
 
924
     lt_dlmutex_seterror *seterror;
 
925
     lt_dlmutex_geterror *geterror;
 
926
{
 
927
  lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func;
 
928
  int                errors     = 0;
 
929
 
 
930
  /* Lock using the old lock() callback, if any.  */
 
931
  LT_DLMUTEX_LOCK ();
 
932
 
 
933
  if ((lock && unlock && seterror && geterror)
 
934
      || !(lock || unlock || seterror || geterror))
 
935
    {
 
936
      lt_dlmutex_lock_func     = lock;
 
937
      lt_dlmutex_unlock_func   = unlock;
 
938
      lt_dlmutex_seterror_func = seterror;
 
939
      lt_dlmutex_geterror_func = geterror;
 
940
    }
 
941
  else
 
942
    {
 
943
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
 
944
      ++errors;
 
945
    }
 
946
 
 
947
  /* Use the old unlock() callback we saved earlier, if any.  Otherwise
 
948
     record any errors using internal storage.  */
 
949
  if (old_unlock)
 
950
    (*old_unlock) ();
 
951
 
 
952
  /* Return the number of errors encountered during the execution of
 
953
     this function.  */
 
954
  return errors;
 
955
}
 
956
 
 
957
 
 
958
 
 
959
 
 
960
/* --- ERROR HANDLING --- */
 
961
 
 
962
 
 
963
static  const char    **user_error_strings      = 0;
 
964
static  int             errorcount              = LT_ERROR_MAX;
 
965
 
 
966
int
 
967
lt_dladderror (diagnostic)
 
968
     const char *diagnostic;
 
969
{
 
970
  int           errindex = 0;
 
971
  int           result   = -1;
 
972
  const char  **temp     = (const char **) 0;
 
973
 
 
974
  assert (diagnostic);
 
975
 
 
976
  LT_DLMUTEX_LOCK ();
 
977
 
 
978
  errindex = errorcount - LT_ERROR_MAX;
 
979
  temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
 
980
  if (temp)
 
981
    {
 
982
      user_error_strings                = temp;
 
983
      user_error_strings[errindex]      = diagnostic;
 
984
      result                            = errorcount++;
 
985
    }
 
986
 
 
987
  LT_DLMUTEX_UNLOCK ();
 
988
 
 
989
  return result;
 
990
}
 
991
 
 
992
int
 
993
lt_dlseterror (errindex)
 
994
     int errindex;
 
995
{
 
996
  int           errors   = 0;
 
997
 
 
998
  LT_DLMUTEX_LOCK ();
 
999
 
 
1000
  if (errindex >= errorcount || errindex < 0)
 
1001
    {
 
1002
      /* Ack!  Error setting the error message! */
 
1003
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
 
1004
      ++errors;
 
1005
    }
 
1006
  else if (errindex < LT_ERROR_MAX)
 
1007
    {
 
1008
      /* No error setting the error message! */
 
1009
      LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
 
1010
    }
 
1011
  else
 
1012
    {
 
1013
      /* No error setting the error message! */
 
1014
      LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
 
1015
    }
 
1016
 
 
1017
  LT_DLMUTEX_UNLOCK ();
 
1018
 
 
1019
  return errors;
 
1020
}
 
1021
 
 
1022
static lt_ptr
 
1023
lt_emalloc (size)
 
1024
     size_t size;
 
1025
{
 
1026
  lt_ptr mem = lt_dlmalloc (size);
 
1027
  if (size && !mem)
 
1028
    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
 
1029
  return mem;
 
1030
}
 
1031
 
 
1032
static lt_ptr
 
1033
lt_erealloc (addr, size)
 
1034
     lt_ptr addr;
 
1035
     size_t size;
 
1036
{
 
1037
  lt_ptr mem = lt_dlrealloc (addr, size);
 
1038
  if (size && !mem)
 
1039
    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
 
1040
  return mem;
 
1041
}
 
1042
 
 
1043
static char *
 
1044
lt_estrdup (str)
 
1045
     const char *str;
 
1046
{
 
1047
  char *copy = strdup (str);
 
1048
  if (LT_STRLEN (str) && !copy)
 
1049
    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
 
1050
  return copy;
 
1051
}
 
1052
 
 
1053
 
 
1054
 
 
1055
 
 
1056
/* --- DLOPEN() INTERFACE LOADER --- */
 
1057
 
 
1058
 
 
1059
#if HAVE_LIBDL
 
1060
 
 
1061
/* dynamic linking with dlopen/dlsym */
 
1062
 
 
1063
#if HAVE_DLFCN_H
 
1064
#  include <dlfcn.h>
 
1065
#endif
 
1066
 
 
1067
#if HAVE_SYS_DL_H
 
1068
#  include <sys/dl.h>
 
1069
#endif
 
1070
 
 
1071
#ifdef RTLD_GLOBAL
 
1072
#  define LT_GLOBAL             RTLD_GLOBAL
 
1073
#else
 
1074
#  ifdef DL_GLOBAL
 
1075
#    define LT_GLOBAL           DL_GLOBAL
 
1076
#  endif
 
1077
#endif /* !RTLD_GLOBAL */
 
1078
#ifndef LT_GLOBAL
 
1079
#  define LT_GLOBAL             0
 
1080
#endif /* !LT_GLOBAL */
 
1081
 
 
1082
/* We may have to define LT_LAZY_OR_NOW in the command line if we
 
1083
   find out it does not work in some platform. */
 
1084
#ifndef LT_LAZY_OR_NOW
 
1085
#  ifdef RTLD_LAZY
 
1086
#    define LT_LAZY_OR_NOW      RTLD_LAZY
 
1087
#  else
 
1088
#    ifdef DL_LAZY
 
1089
#      define LT_LAZY_OR_NOW    DL_LAZY
 
1090
#    endif
 
1091
#  endif /* !RTLD_LAZY */
 
1092
#endif
 
1093
#ifndef LT_LAZY_OR_NOW
 
1094
#  ifdef RTLD_NOW
 
1095
#    define LT_LAZY_OR_NOW      RTLD_NOW
 
1096
#  else
 
1097
#    ifdef DL_NOW
 
1098
#      define LT_LAZY_OR_NOW    DL_NOW
 
1099
#    endif
 
1100
#  endif /* !RTLD_NOW */
 
1101
#endif
 
1102
#ifndef LT_LAZY_OR_NOW
 
1103
#  define LT_LAZY_OR_NOW        0
 
1104
#endif /* !LT_LAZY_OR_NOW */
 
1105
 
 
1106
#if HAVE_DLERROR
 
1107
#  define DLERROR(arg)  dlerror ()
 
1108
#else
 
1109
#  define DLERROR(arg)  LT_DLSTRERROR (arg)
 
1110
#endif
 
1111
 
 
1112
static lt_module
 
1113
sys_dl_open (loader_data, filename)
 
1114
     lt_user_data loader_data;
 
1115
     const char *filename;
 
1116
{
 
1117
  lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
 
1118
 
 
1119
  if (!module)
 
1120
    {
 
1121
      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
 
1122
    }
 
1123
 
 
1124
  return module;
 
1125
}
 
1126
 
 
1127
static int
 
1128
sys_dl_close (loader_data, module)
 
1129
     lt_user_data loader_data;
 
1130
     lt_module module;
 
1131
{
 
1132
  int errors = 0;
 
1133
 
 
1134
  if (dlclose (module) != 0)
 
1135
    {
 
1136
      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
 
1137
      ++errors;
 
1138
    }
 
1139
 
 
1140
  return errors;
 
1141
}
 
1142
 
 
1143
static lt_ptr
 
1144
sys_dl_sym (loader_data, module, symbol)
 
1145
     lt_user_data loader_data;
 
1146
     lt_module module;
 
1147
     const char *symbol;
 
1148
{
 
1149
  lt_ptr address = dlsym (module, symbol);
 
1150
 
 
1151
  if (!address)
 
1152
    {
 
1153
      LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
 
1154
    }
 
1155
 
 
1156
  return address;
 
1157
}
 
1158
 
 
1159
static struct lt_user_dlloader sys_dl =
 
1160
  {
 
1161
#  ifdef NEED_USCORE
 
1162
    "_",
 
1163
#  else
 
1164
    0,
 
1165
#  endif
 
1166
    sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
 
1167
 
 
1168
 
 
1169
#endif /* HAVE_LIBDL */
 
1170
 
 
1171
 
 
1172
 
 
1173
/* --- SHL_LOAD() INTERFACE LOADER --- */
 
1174
 
 
1175
#if HAVE_SHL_LOAD
 
1176
 
 
1177
/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
 
1178
 
 
1179
#ifdef HAVE_DL_H
 
1180
#  include <dl.h>
 
1181
#endif
 
1182
 
 
1183
/* some flags are missing on some systems, so we provide
 
1184
 * harmless defaults.
 
1185
 *
 
1186
 * Mandatory:
 
1187
 * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
 
1188
 * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
 
1189
 *
 
1190
 * Optionally:
 
1191
 * BIND_FIRST      - Place the library at the head of the symbol search
 
1192
 *                   order.
 
1193
 * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
 
1194
 *                   unsatisfied symbols as fatal.  This flag allows
 
1195
 *                   binding of unsatisfied code symbols to be deferred
 
1196
 *                   until use.
 
1197
 *                   [Perl: For certain libraries, like DCE, deferred
 
1198
 *                   binding often causes run time problems. Adding
 
1199
 *                   BIND_NONFATAL to BIND_IMMEDIATE still allows
 
1200
 *                   unresolved references in situations like this.]
 
1201
 * BIND_NOSTART    - Do not call the initializer for the shared library
 
1202
 *                   when the library is loaded, nor on a future call to
 
1203
 *                   shl_unload().
 
1204
 * BIND_VERBOSE    - Print verbose messages concerning possible
 
1205
 *                   unsatisfied symbols.
 
1206
 *
 
1207
 * hp9000s700/hp9000s800:
 
1208
 * BIND_RESTRICTED - Restrict symbols visible by the library to those
 
1209
 *                   present at library load time.
 
1210
 * DYNAMIC_PATH    - Allow the loader to dynamically search for the
 
1211
 *                   library specified by the path argument.
 
1212
 */
 
1213
 
 
1214
#ifndef DYNAMIC_PATH
 
1215
#  define DYNAMIC_PATH          0
 
1216
#endif
 
1217
#ifndef BIND_RESTRICTED
 
1218
#  define BIND_RESTRICTED       0
 
1219
#endif
 
1220
 
 
1221
#define LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
 
1222
 
 
1223
static lt_module
 
1224
sys_shl_open (loader_data, filename)
 
1225
     lt_user_data loader_data;
 
1226
     const char *filename;
 
1227
{
 
1228
  static shl_t self = (shl_t) 0;
 
1229
  lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
 
1230
 
 
1231
  /* Since searching for a symbol against a NULL module handle will also
 
1232
     look in everything else that was already loaded and exported with
 
1233
     the -E compiler flag, we always cache a handle saved before any
 
1234
     modules are loaded.  */
 
1235
  if (!self)
 
1236
    {
 
1237
      lt_ptr address;
 
1238
      shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
 
1239
    }
 
1240
 
 
1241
  if (!filename)
 
1242
    {
 
1243
      module = self;
 
1244
    }
 
1245
  else
 
1246
    {
 
1247
      module = shl_load (filename, LT_BIND_FLAGS, 0L);
 
1248
 
 
1249
      if (!module)
 
1250
        {
 
1251
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
 
1252
        }
 
1253
    }
 
1254
 
 
1255
  return module;
 
1256
}
 
1257
 
 
1258
static int
 
1259
sys_shl_close (loader_data, module)
 
1260
     lt_user_data loader_data;
 
1261
     lt_module module;
 
1262
{
 
1263
  int errors = 0;
 
1264
 
 
1265
  if (module && (shl_unload ((shl_t) (module)) != 0))
 
1266
    {
 
1267
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
 
1268
      ++errors;
 
1269
    }
 
1270
 
 
1271
  return errors;
 
1272
}
 
1273
 
 
1274
static lt_ptr
 
1275
sys_shl_sym (loader_data, module, symbol)
 
1276
     lt_user_data loader_data;
 
1277
     lt_module module;
 
1278
     const char *symbol;
 
1279
{
 
1280
  lt_ptr address = 0;
 
1281
 
 
1282
  /* sys_shl_open should never return a NULL module handle */
 
1283
  if (module == (lt_module) 0)
 
1284
  {
 
1285
    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
1286
  }
 
1287
  else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
 
1288
    {
 
1289
      if (!address)
 
1290
        {
 
1291
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
1292
        }
 
1293
    }
 
1294
 
 
1295
  return address;
 
1296
}
 
1297
 
 
1298
static struct lt_user_dlloader sys_shl = {
 
1299
  0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
 
1300
};
 
1301
 
 
1302
#endif /* HAVE_SHL_LOAD */
 
1303
 
 
1304
 
 
1305
 
 
1306
 
 
1307
/* --- LOADLIBRARY() INTERFACE LOADER --- */
 
1308
 
 
1309
#ifdef __WINDOWS__
 
1310
 
 
1311
/* dynamic linking for Win32 */
 
1312
 
 
1313
#include <windows.h>
 
1314
 
 
1315
/* Forward declaration; required to implement handle search below. */
 
1316
static lt_dlhandle handles;
 
1317
 
 
1318
static lt_module
 
1319
sys_wll_open (loader_data, filename)
 
1320
     lt_user_data loader_data;
 
1321
     const char *filename;
 
1322
{
 
1323
  lt_dlhandle   cur;
 
1324
  lt_module     module     = 0;
 
1325
  const char   *errormsg   = 0;
 
1326
  char         *searchname = 0;
 
1327
  char         *ext;
 
1328
  char          self_name_buf[MAX_PATH];
 
1329
 
 
1330
  if (!filename)
 
1331
    {
 
1332
      /* Get the name of main module */
 
1333
      *self_name_buf = 0;
 
1334
      GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
 
1335
      filename = ext = self_name_buf;
 
1336
    }
 
1337
  else
 
1338
    {
 
1339
      ext = strrchr (filename, '.');
 
1340
    }
 
1341
 
 
1342
  if (ext)
 
1343
    {
 
1344
      /* FILENAME already has an extension. */
 
1345
      searchname = lt_estrdup (filename);
 
1346
    }
 
1347
  else
 
1348
    {
 
1349
      /* Append a `.' to stop Windows from adding an
 
1350
         implicit `.dll' extension. */
 
1351
      searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
 
1352
      if (searchname)
 
1353
        sprintf (searchname, "%s.", filename);
 
1354
    }
 
1355
  if (!searchname)
 
1356
    return 0;
 
1357
 
 
1358
  {
 
1359
    /* Silence dialog from LoadLibrary on some failures.
 
1360
       No way to get the error mode, but to set it,
 
1361
       so set it twice to preserve any previous flags. */
 
1362
    UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
 
1363
    SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
 
1364
 
 
1365
#if defined(__CYGWIN__)
 
1366
    {
 
1367
      char wpath[MAX_PATH];
 
1368
      cygwin_conv_to_full_win32_path (searchname, wpath);
 
1369
      module = LoadLibrary (wpath);
 
1370
    }
 
1371
#else
 
1372
    module = LoadLibrary (searchname);
 
1373
#endif
 
1374
 
 
1375
    /* Restore the error mode. */
 
1376
    SetErrorMode(errormode);
 
1377
  }
 
1378
 
 
1379
  LT_DLFREE (searchname);
 
1380
 
 
1381
  /* libltdl expects this function to fail if it is unable
 
1382
     to physically load the library.  Sadly, LoadLibrary
 
1383
     will search the loaded libraries for a match and return
 
1384
     one of them if the path search load fails.
 
1385
 
 
1386
     We check whether LoadLibrary is returning a handle to
 
1387
     an already loaded module, and simulate failure if we
 
1388
     find one. */
 
1389
  LT_DLMUTEX_LOCK ();
 
1390
  cur = handles;
 
1391
  while (cur)
 
1392
    {
 
1393
      if (!cur->module)
 
1394
        {
 
1395
          cur = 0;
 
1396
          break;
 
1397
        }
 
1398
 
 
1399
      if (cur->module == module)
 
1400
        {
 
1401
          break;
 
1402
        }
 
1403
 
 
1404
      cur = cur->next;
 
1405
  }
 
1406
  LT_DLMUTEX_UNLOCK ();
 
1407
 
 
1408
  if (cur || !module)
 
1409
    {
 
1410
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
 
1411
      module = 0;
 
1412
    }
 
1413
 
 
1414
  return module;
 
1415
}
 
1416
 
 
1417
static int
 
1418
sys_wll_close (loader_data, module)
 
1419
     lt_user_data loader_data;
 
1420
     lt_module module;
 
1421
{
 
1422
  int         errors   = 0;
 
1423
 
 
1424
  if (FreeLibrary(module) == 0)
 
1425
    {
 
1426
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
 
1427
      ++errors;
 
1428
    }
 
1429
 
 
1430
  return errors;
 
1431
}
 
1432
 
 
1433
static lt_ptr
 
1434
sys_wll_sym (loader_data, module, symbol)
 
1435
     lt_user_data loader_data;
 
1436
     lt_module module;
 
1437
     const char *symbol;
 
1438
{
 
1439
  lt_ptr      address  = GetProcAddress (module, symbol);
 
1440
 
 
1441
  if (!address)
 
1442
    {
 
1443
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
1444
    }
 
1445
 
 
1446
  return address;
 
1447
}
 
1448
 
 
1449
static struct lt_user_dlloader sys_wll = {
 
1450
  0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
 
1451
};
 
1452
 
 
1453
#endif /* __WINDOWS__ */
 
1454
 
 
1455
 
 
1456
 
 
1457
 
 
1458
/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
 
1459
 
 
1460
 
 
1461
#ifdef __BEOS__
 
1462
 
 
1463
/* dynamic linking for BeOS */
 
1464
 
 
1465
#include <kernel/image.h>
 
1466
 
 
1467
static lt_module
 
1468
sys_bedl_open (loader_data, filename)
 
1469
     lt_user_data loader_data;
 
1470
     const char *filename;
 
1471
{
 
1472
  image_id image = 0;
 
1473
 
 
1474
  if (filename)
 
1475
    {
 
1476
      image = load_add_on (filename);
 
1477
    }
 
1478
  else
 
1479
    {
 
1480
      image_info info;
 
1481
      int32 cookie = 0;
 
1482
      if (get_next_image_info (0, &cookie, &info) == B_OK)
 
1483
        image = load_add_on (info.name);
 
1484
    }
 
1485
 
 
1486
  if (image <= 0)
 
1487
    {
 
1488
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
 
1489
      image = 0;
 
1490
    }
 
1491
 
 
1492
  return (lt_module) image;
 
1493
}
 
1494
 
 
1495
static int
 
1496
sys_bedl_close (loader_data, module)
 
1497
     lt_user_data loader_data;
 
1498
     lt_module module;
 
1499
{
 
1500
  int errors = 0;
 
1501
 
 
1502
  if (unload_add_on ((image_id) module) != B_OK)
 
1503
    {
 
1504
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
 
1505
      ++errors;
 
1506
    }
 
1507
 
 
1508
  return errors;
 
1509
}
 
1510
 
 
1511
static lt_ptr
 
1512
sys_bedl_sym (loader_data, module, symbol)
 
1513
     lt_user_data loader_data;
 
1514
     lt_module module;
 
1515
     const char *symbol;
 
1516
{
 
1517
  lt_ptr address = 0;
 
1518
  image_id image = (image_id) module;
 
1519
 
 
1520
  if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
 
1521
    {
 
1522
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
1523
      address = 0;
 
1524
    }
 
1525
 
 
1526
  return address;
 
1527
}
 
1528
 
 
1529
static struct lt_user_dlloader sys_bedl = {
 
1530
  0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
 
1531
};
 
1532
 
 
1533
#endif /* __BEOS__ */
 
1534
 
 
1535
 
 
1536
 
 
1537
 
 
1538
/* --- DLD_LINK() INTERFACE LOADER --- */
 
1539
 
 
1540
 
 
1541
#if HAVE_DLD
 
1542
 
 
1543
/* dynamic linking with dld */
 
1544
 
 
1545
#if HAVE_DLD_H
 
1546
#include <dld.h>
 
1547
#endif
 
1548
 
 
1549
static lt_module
 
1550
sys_dld_open (loader_data, filename)
 
1551
     lt_user_data loader_data;
 
1552
     const char *filename;
 
1553
{
 
1554
  lt_module module = strdup (filename);
 
1555
 
 
1556
  if (dld_link (filename) != 0)
 
1557
    {
 
1558
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
 
1559
      LT_DLFREE (module);
 
1560
      module = 0;
 
1561
    }
 
1562
 
 
1563
  return module;
 
1564
}
 
1565
 
 
1566
static int
 
1567
sys_dld_close (loader_data, module)
 
1568
     lt_user_data loader_data;
 
1569
     lt_module module;
 
1570
{
 
1571
  int errors = 0;
 
1572
 
 
1573
  if (dld_unlink_by_file ((char*)(module), 1) != 0)
 
1574
    {
 
1575
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
 
1576
      ++errors;
 
1577
    }
 
1578
  else
 
1579
    {
 
1580
      LT_DLFREE (module);
 
1581
    }
 
1582
 
 
1583
  return errors;
 
1584
}
 
1585
 
 
1586
static lt_ptr
 
1587
sys_dld_sym (loader_data, module, symbol)
 
1588
     lt_user_data loader_data;
 
1589
     lt_module module;
 
1590
     const char *symbol;
 
1591
{
 
1592
  lt_ptr address = dld_get_func (symbol);
 
1593
 
 
1594
  if (!address)
 
1595
    {
 
1596
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
1597
    }
 
1598
 
 
1599
  return address;
 
1600
}
 
1601
 
 
1602
static struct lt_user_dlloader sys_dld = {
 
1603
  0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
 
1604
};
 
1605
 
 
1606
#endif /* HAVE_DLD */
 
1607
 
 
1608
/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
 
1609
#if HAVE_DYLD
 
1610
 
 
1611
 
 
1612
#if HAVE_MACH_O_DYLD_H
 
1613
#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
 
1614
/* Is this correct? Does it still function properly? */
 
1615
#define __private_extern__ extern
 
1616
#endif
 
1617
# include <mach-o/dyld.h>
 
1618
#endif
 
1619
#include <mach-o/getsect.h>
 
1620
 
 
1621
/* We have to put some stuff here that isn't in older dyld.h files */
 
1622
#ifndef ENUM_DYLD_BOOL
 
1623
# define ENUM_DYLD_BOOL
 
1624
# undef FALSE
 
1625
# undef TRUE
 
1626
 enum DYLD_BOOL {
 
1627
    FALSE,
 
1628
    TRUE
 
1629
 };
 
1630
#endif
 
1631
#ifndef LC_REQ_DYLD
 
1632
# define LC_REQ_DYLD 0x80000000
 
1633
#endif
 
1634
#ifndef LC_LOAD_WEAK_DYLIB
 
1635
# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
 
1636
#endif
 
1637
static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
 
1638
static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
 
1639
static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
 
1640
static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
 
1641
 
 
1642
#ifndef NSADDIMAGE_OPTION_NONE
 
1643
#define NSADDIMAGE_OPTION_NONE                          0x0
 
1644
#endif
 
1645
#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
 
1646
#define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
 
1647
#endif
 
1648
#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
 
1649
#define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
 
1650
#endif
 
1651
#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
 
1652
#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
 
1653
#endif
 
1654
#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
 
1655
#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
 
1656
#endif
 
1657
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
 
1658
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
 
1659
#endif
 
1660
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
 
1661
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
 
1662
#endif
 
1663
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
 
1664
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
 
1665
#endif
 
1666
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
 
1667
#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
 
1668
#endif
 
1669
 
 
1670
 
 
1671
static const char *
 
1672
lt_int_dyld_error(othererror)
 
1673
        char* othererror;
 
1674
{
 
1675
/* return the dyld error string, or the passed in error string if none */
 
1676
        NSLinkEditErrors ler;
 
1677
        int lerno;
 
1678
        const char *errstr;
 
1679
        const char *file;
 
1680
        NSLinkEditError(&ler,&lerno,&file,&errstr);
 
1681
        if (!errstr || !strlen(errstr)) errstr = othererror;
 
1682
        return errstr;
 
1683
}
 
1684
 
 
1685
static const struct mach_header *
 
1686
lt_int_dyld_get_mach_header_from_nsmodule(module)
 
1687
        NSModule module;
 
1688
{
 
1689
/* There should probably be an apple dyld api for this */
 
1690
        int i=_dyld_image_count();
 
1691
        int j;
 
1692
        const char *modname=NSNameOfModule(module);
 
1693
        const struct mach_header *mh=NULL;
 
1694
        if (!modname) return NULL;
 
1695
        for (j = 0; j < i; j++)
 
1696
        {
 
1697
                if (!strcmp(_dyld_get_image_name(j),modname))
 
1698
                {
 
1699
                        mh=_dyld_get_image_header(j);
 
1700
                        break;
 
1701
                }
 
1702
        }
 
1703
        return mh;
 
1704
}
 
1705
 
 
1706
static const char* lt_int_dyld_lib_install_name(mh)
 
1707
        const struct mach_header *mh;
 
1708
{
 
1709
/* NSAddImage is also used to get the loaded image, but it only works if the lib
 
1710
   is installed, for uninstalled libs we need to check the install_names against
 
1711
   each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
 
1712
   different lib was loaded as a result
 
1713
*/
 
1714
        int j;
 
1715
        struct load_command *lc;
 
1716
        unsigned long offset = sizeof(struct mach_header);
 
1717
        const char* retStr=NULL;
 
1718
        for (j = 0; j < mh->ncmds; j++)
 
1719
        {
 
1720
                lc = (struct load_command*)(((unsigned long)mh) + offset);
 
1721
                if (LC_ID_DYLIB == lc->cmd)
 
1722
                {
 
1723
                        retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
 
1724
                                                                        (unsigned long)lc);
 
1725
                }
 
1726
                offset += lc->cmdsize;
 
1727
        }
 
1728
        return retStr;
 
1729
}
 
1730
 
 
1731
static const struct mach_header *
 
1732
lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
 
1733
{
 
1734
        int i=_dyld_image_count();
 
1735
        int j;
 
1736
        const struct mach_header *mh=NULL;
 
1737
        const char *id=NULL;
 
1738
        for (j = 0; j < i; j++)
 
1739
        {
 
1740
                id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
 
1741
                if ((id) && (!strcmp(id,name)))
 
1742
                {
 
1743
                        mh=_dyld_get_image_header(j);
 
1744
                        break;
 
1745
                }
 
1746
        }
 
1747
        return mh;
 
1748
}
 
1749
 
 
1750
static NSSymbol
 
1751
lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
 
1752
        const char *symbol;
 
1753
        const struct mach_header *mh;
 
1754
{
 
1755
        /* Safe to assume our mh is good */
 
1756
        int j;
 
1757
        struct load_command *lc;
 
1758
        unsigned long offset = sizeof(struct mach_header);
 
1759
        NSSymbol retSym = 0;
 
1760
        const struct mach_header *mh1;
 
1761
        if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
 
1762
        {
 
1763
                for (j = 0; j < mh->ncmds; j++)
 
1764
                {
 
1765
                        lc = (struct load_command*)(((unsigned long)mh) + offset);
 
1766
                        if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
 
1767
                        {
 
1768
                                mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
 
1769
                                                                                (unsigned long)lc));
 
1770
                                if (!mh1)
 
1771
                                {
 
1772
                                        /* Maybe NSAddImage can find it */
 
1773
                                        mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
 
1774
                                                                                (unsigned long)lc),
 
1775
                                                                                NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
 
1776
                                                                                NSADDIMAGE_OPTION_WITH_SEARCHING +
 
1777
                                                                                NSADDIMAGE_OPTION_RETURN_ON_ERROR );
 
1778
                                }
 
1779
                                if (mh1)
 
1780
                                {
 
1781
                                        retSym = ltdl_NSLookupSymbolInImage(mh1,
 
1782
                                                                                        symbol,
 
1783
                                                                                        NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
 
1784
                                                                                        | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
 
1785
                                                                                        );
 
1786
                                        if (retSym) break;
 
1787
                                }
 
1788
                        }
 
1789
                        offset += lc->cmdsize;
 
1790
                }
 
1791
        }
 
1792
        return retSym;
 
1793
}
 
1794
 
 
1795
static int
 
1796
sys_dyld_init()
 
1797
{
 
1798
        int retCode = 0;
 
1799
        int err = 0;
 
1800
        if (!_dyld_present()) {
 
1801
                retCode=1;
 
1802
        }
 
1803
        else {
 
1804
      err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
 
1805
      err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
 
1806
      err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
 
1807
      err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
 
1808
    }
 
1809
 return retCode;
 
1810
}
 
1811
 
 
1812
static lt_module
 
1813
sys_dyld_open (loader_data, filename)
 
1814
     lt_user_data loader_data;
 
1815
     const char *filename;
 
1816
{
 
1817
        lt_module   module   = 0;
 
1818
        NSObjectFileImage ofi = 0;
 
1819
        NSObjectFileImageReturnCode ofirc;
 
1820
 
 
1821
        if (!filename)
 
1822
                return (lt_module)-1;
 
1823
        ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
 
1824
        switch (ofirc)
 
1825
        {
 
1826
                case NSObjectFileImageSuccess:
 
1827
                        module = NSLinkModule(ofi, filename,
 
1828
                                                NSLINKMODULE_OPTION_RETURN_ON_ERROR
 
1829
                                                 | NSLINKMODULE_OPTION_PRIVATE
 
1830
                                                 | NSLINKMODULE_OPTION_BINDNOW);
 
1831
                        NSDestroyObjectFileImage(ofi);
 
1832
                        if (module)
 
1833
                                ltdl_NSMakePrivateModulePublic(module);
 
1834
                        break;
 
1835
                case NSObjectFileImageInappropriateFile:
 
1836
                    if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
 
1837
                    {
 
1838
                                module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
 
1839
                                break;
 
1840
                        }
 
1841
                default:
 
1842
                        LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
 
1843
                        return 0;
 
1844
        }
 
1845
        if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
 
1846
  return module;
 
1847
}
 
1848
 
 
1849
static int
 
1850
sys_dyld_close (loader_data, module)
 
1851
     lt_user_data loader_data;
 
1852
     lt_module module;
 
1853
{
 
1854
        int retCode = 0;
 
1855
        int flags = 0;
 
1856
        if (module == (lt_module)-1) return 0;
 
1857
#ifdef __BIG_ENDIAN__
 
1858
        if (((struct mach_header *)module)->magic == MH_MAGIC)
 
1859
#else
 
1860
    if (((struct mach_header *)module)->magic == MH_CIGAM)
 
1861
#endif
 
1862
        {
 
1863
          LT_DLMUTEX_SETERROR("Can not close a dylib");
 
1864
          retCode = 1;
 
1865
        }
 
1866
        else
 
1867
        {
 
1868
#if 1
 
1869
/* Currently, if a module contains c++ static destructors and it is unloaded, we
 
1870
   get a segfault in atexit(), due to compiler and dynamic loader differences of
 
1871
   opinion, this works around that.
 
1872
*/
 
1873
                if ((const struct section *)NULL !=
 
1874
                   getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
 
1875
                   "__DATA","__mod_term_func"))
 
1876
                {
 
1877
                        flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
 
1878
                }
 
1879
#endif
 
1880
#ifdef __ppc__
 
1881
                        flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
 
1882
#endif
 
1883
                if (!NSUnLinkModule(module,flags))
 
1884
                {
 
1885
                        retCode=1;
 
1886
                        LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
 
1887
                }
 
1888
        }
 
1889
 
 
1890
 return retCode;
 
1891
}
 
1892
 
 
1893
static lt_ptr
 
1894
sys_dyld_sym (loader_data, module, symbol)
 
1895
     lt_user_data loader_data;
 
1896
     lt_module module;
 
1897
     const char *symbol;
 
1898
{
 
1899
        lt_ptr address = 0;
 
1900
        NSSymbol *nssym = 0;
 
1901
        void *unused;
 
1902
        const struct mach_header *mh=NULL;
 
1903
        char saveError[256] = "Symbol not found";
 
1904
        if (module == (lt_module)-1)
 
1905
        {
 
1906
                _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
 
1907
                return address;
 
1908
        }
 
1909
#ifdef __BIG_ENDIAN__
 
1910
        if (((struct mach_header *)module)->magic == MH_MAGIC)
 
1911
#else
 
1912
    if (((struct mach_header *)module)->magic == MH_CIGAM)
 
1913
#endif
 
1914
        {
 
1915
            if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
 
1916
            {
 
1917
                mh=module;
 
1918
                        if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
 
1919
                        {
 
1920
                                nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
 
1921
                                                                                        symbol,
 
1922
                                                                                        NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
 
1923
                                                                                        | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
 
1924
                                                                                        );
 
1925
                        }
 
1926
            }
 
1927
 
 
1928
        }
 
1929
  else {
 
1930
        nssym = NSLookupSymbolInModule(module, symbol);
 
1931
        }
 
1932
        if (!nssym)
 
1933
        {
 
1934
                strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
 
1935
                saveError[255] = 0;
 
1936
                if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
 
1937
                nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
 
1938
        }
 
1939
        if (!nssym)
 
1940
        {
 
1941
                LT_DLMUTEX_SETERROR (saveError);
 
1942
                return NULL;
 
1943
        }
 
1944
        return NSAddressOfSymbol(nssym);
 
1945
}
 
1946
 
 
1947
static struct lt_user_dlloader sys_dyld =
 
1948
  { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
 
1949
 
 
1950
 
 
1951
#endif /* HAVE_DYLD */
 
1952
 
 
1953
 
 
1954
/* --- DLPREOPEN() INTERFACE LOADER --- */
 
1955
 
 
1956
 
 
1957
/* emulate dynamic linking using preloaded_symbols */
 
1958
 
 
1959
typedef struct lt_dlsymlists_t
 
1960
{
 
1961
  struct lt_dlsymlists_t       *next;
 
1962
  const lt_dlsymlist           *syms;
 
1963
} lt_dlsymlists_t;
 
1964
 
 
1965
static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
 
1966
static  lt_dlsymlists_t        *preloaded_symbols               = 0;
 
1967
 
 
1968
static int
 
1969
presym_init (loader_data)
 
1970
     lt_user_data loader_data;
 
1971
{
 
1972
  int errors = 0;
 
1973
 
 
1974
  LT_DLMUTEX_LOCK ();
 
1975
 
 
1976
  preloaded_symbols = 0;
 
1977
  if (default_preloaded_symbols)
 
1978
    {
 
1979
      errors = lt_dlpreload (default_preloaded_symbols);
 
1980
    }
 
1981
 
 
1982
  LT_DLMUTEX_UNLOCK ();
 
1983
 
 
1984
  return errors;
 
1985
}
 
1986
 
 
1987
static int
 
1988
presym_free_symlists ()
 
1989
{
 
1990
  lt_dlsymlists_t *lists;
 
1991
 
 
1992
  LT_DLMUTEX_LOCK ();
 
1993
 
 
1994
  lists = preloaded_symbols;
 
1995
  while (lists)
 
1996
    {
 
1997
      lt_dlsymlists_t   *tmp = lists;
 
1998
 
 
1999
      lists = lists->next;
 
2000
      LT_DLFREE (tmp);
 
2001
    }
 
2002
  preloaded_symbols = 0;
 
2003
 
 
2004
  LT_DLMUTEX_UNLOCK ();
 
2005
 
 
2006
  return 0;
 
2007
}
 
2008
 
 
2009
static int
 
2010
presym_exit (loader_data)
 
2011
     lt_user_data loader_data;
 
2012
{
 
2013
  presym_free_symlists ();
 
2014
  return 0;
 
2015
}
 
2016
 
 
2017
static int
 
2018
presym_add_symlist (preloaded)
 
2019
     const lt_dlsymlist *preloaded;
 
2020
{
 
2021
  lt_dlsymlists_t *tmp;
 
2022
  lt_dlsymlists_t *lists;
 
2023
  int              errors   = 0;
 
2024
 
 
2025
  LT_DLMUTEX_LOCK ();
 
2026
 
 
2027
  lists = preloaded_symbols;
 
2028
  while (lists)
 
2029
    {
 
2030
      if (lists->syms == preloaded)
 
2031
        {
 
2032
          goto done;
 
2033
        }
 
2034
      lists = lists->next;
 
2035
    }
 
2036
 
 
2037
  tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
 
2038
  if (tmp)
 
2039
    {
 
2040
      memset (tmp, 0, sizeof(lt_dlsymlists_t));
 
2041
      tmp->syms = preloaded;
 
2042
      tmp->next = preloaded_symbols;
 
2043
      preloaded_symbols = tmp;
 
2044
    }
 
2045
  else
 
2046
    {
 
2047
      ++errors;
 
2048
    }
 
2049
 
 
2050
 done:
 
2051
  LT_DLMUTEX_UNLOCK ();
 
2052
  return errors;
 
2053
}
 
2054
 
 
2055
static lt_module
 
2056
presym_open (loader_data, filename)
 
2057
     lt_user_data loader_data;
 
2058
     const char *filename;
 
2059
{
 
2060
  lt_dlsymlists_t *lists;
 
2061
  lt_module        module = (lt_module) 0;
 
2062
 
 
2063
  LT_DLMUTEX_LOCK ();
 
2064
  lists = preloaded_symbols;
 
2065
 
 
2066
  if (!lists)
 
2067
    {
 
2068
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
 
2069
      goto done;
 
2070
    }
 
2071
 
 
2072
  /* Can't use NULL as the reflective symbol header, as NULL is
 
2073
     used to mark the end of the entire symbol list.  Self-dlpreopened
 
2074
     symbols follow this magic number, chosen to be an unlikely
 
2075
     clash with a real module name.  */
 
2076
  if (!filename)
 
2077
    {
 
2078
      filename = "@PROGRAM@";
 
2079
    }
 
2080
 
 
2081
  while (lists)
 
2082
    {
 
2083
      const lt_dlsymlist *syms = lists->syms;
 
2084
 
 
2085
      while (syms->name)
 
2086
        {
 
2087
          if (!syms->address && strcmp(syms->name, filename) == 0)
 
2088
            {
 
2089
              module = (lt_module) syms;
 
2090
              goto done;
 
2091
            }
 
2092
          ++syms;
 
2093
        }
 
2094
 
 
2095
      lists = lists->next;
 
2096
    }
 
2097
 
 
2098
  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
 
2099
 
 
2100
 done:
 
2101
  LT_DLMUTEX_UNLOCK ();
 
2102
  return module;
 
2103
}
 
2104
 
 
2105
static int
 
2106
presym_close (loader_data, module)
 
2107
     lt_user_data loader_data;
 
2108
     lt_module module;
 
2109
{
 
2110
  /* Just to silence gcc -Wall */
 
2111
  module = 0;
 
2112
  return 0;
 
2113
}
 
2114
 
 
2115
static lt_ptr
 
2116
presym_sym (loader_data, module, symbol)
 
2117
     lt_user_data loader_data;
 
2118
     lt_module module;
 
2119
     const char *symbol;
 
2120
{
 
2121
  lt_dlsymlist *syms = (lt_dlsymlist*) module;
 
2122
 
 
2123
  ++syms;
 
2124
  while (syms->address)
 
2125
    {
 
2126
      if (strcmp(syms->name, symbol) == 0)
 
2127
        {
 
2128
          return syms->address;
 
2129
        }
 
2130
 
 
2131
    ++syms;
 
2132
  }
 
2133
 
 
2134
  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
2135
 
 
2136
  return 0;
 
2137
}
 
2138
 
 
2139
static struct lt_user_dlloader presym = {
 
2140
  0, presym_open, presym_close, presym_sym, presym_exit, 0
 
2141
};
 
2142
 
 
2143
 
 
2144
 
 
2145
 
 
2146
 
 
2147
/* --- DYNAMIC MODULE LOADING --- */
 
2148
 
 
2149
 
 
2150
/* The type of a function used at each iteration of  foreach_dirinpath().  */
 
2151
typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
 
2152
                                                 lt_ptr data2));
 
2153
/* foreachfile_callback itself calls a function of this type: */
 
2154
typedef int     file_worker_func      LT_PARAMS((const char *filename, void *data));
 
2155
 
 
2156
static  int     foreach_dirinpath     LT_PARAMS((const char *search_path,
 
2157
                                                 const char *base_name,
 
2158
                                                 foreach_callback_func *func,
 
2159
                                                 lt_ptr data1, lt_ptr data2));
 
2160
 
 
2161
static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
 
2162
                                                 lt_ptr ignored));
 
2163
static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
 
2164
                                                 lt_ptr ignored));
 
2165
static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
 
2166
                                                 lt_ptr data2));
 
2167
 
 
2168
 
 
2169
static  int     canonicalize_path     LT_PARAMS((const char *path,
 
2170
                                                 char **pcanonical));
 
2171
static  int     argzize_path          LT_PARAMS((const char *path,
 
2172
                                                 char **pargz,
 
2173
                                                 size_t *pargz_len));
 
2174
static  FILE   *find_file             LT_PARAMS((const char *search_path,
 
2175
                                                 const char *base_name,
 
2176
                                                 char **pdir));
 
2177
static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
 
2178
                                                 const char *base_name,
 
2179
                                                 lt_dlhandle *handle));
 
2180
static  int     find_module           LT_PARAMS((lt_dlhandle *handle,
 
2181
                                                 const char *dir,
 
2182
                                                 const char *libdir,
 
2183
                                                 const char *dlname,
 
2184
                                                 const char *old_name,
 
2185
                                                 int installed));
 
2186
static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
 
2187
                                                 char *libdir, char *deplibs));
 
2188
static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
 
2189
                                                 char *deplibs));
 
2190
static  int     trim                  LT_PARAMS((char **dest,
 
2191
                                                 const char *str));
 
2192
static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
 
2193
                                                 const char *filename));
 
2194
static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
 
2195
                                                 const char *filename));
 
2196
static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
 
2197
static  int     lt_argz_insert        LT_PARAMS((char **pargz,
 
2198
                                                 size_t *pargz_len,
 
2199
                                                 char *before,
 
2200
                                                 const char *entry));
 
2201
static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
 
2202
                                                 size_t *pargz_len,
 
2203
                                                 const char *entry));
 
2204
static  int     lt_argz_insertdir     LT_PARAMS((char **pargz,
 
2205
                                                 size_t *pargz_len,
 
2206
                                                 const char *dirnam,
 
2207
                                                 struct dirent *dp));
 
2208
static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
 
2209
                                                 char *before,
 
2210
                                                 const char *dir));
 
2211
static  int     list_files_by_dir     LT_PARAMS((const char *dirnam,
 
2212
                                                 char **pargz,
 
2213
                                                 size_t *pargz_len));
 
2214
static  int     file_not_found        LT_PARAMS((void));
 
2215
 
 
2216
static  char           *user_search_path= 0;
 
2217
static  lt_dlloader    *loaders         = 0;
 
2218
static  lt_dlhandle     handles         = 0;
 
2219
static  int             initialized     = 0;
 
2220
 
 
2221
/* Initialize libltdl. */
 
2222
int
 
2223
lt_dlinit ()
 
2224
{
 
2225
  int         errors   = 0;
 
2226
 
 
2227
  LT_DLMUTEX_LOCK ();
 
2228
 
 
2229
  /* Initialize only at first call. */
 
2230
  if (++initialized == 1)
 
2231
    {
 
2232
      handles = 0;
 
2233
      user_search_path = 0; /* empty search path */
 
2234
 
 
2235
#if HAVE_LIBDL
 
2236
      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
 
2237
#endif
 
2238
#if HAVE_SHL_LOAD
 
2239
      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
 
2240
#endif
 
2241
#ifdef __WINDOWS__
 
2242
      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
 
2243
#endif
 
2244
#ifdef __BEOS__
 
2245
      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
 
2246
#endif
 
2247
#if HAVE_DLD
 
2248
      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
 
2249
#endif
 
2250
#if HAVE_DYLD
 
2251
       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
 
2252
       errors += sys_dyld_init();
 
2253
#endif
 
2254
      errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
 
2255
 
 
2256
      if (presym_init (presym.dlloader_data))
 
2257
        {
 
2258
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
 
2259
          ++errors;
 
2260
        }
 
2261
      else if (errors != 0)
 
2262
        {
 
2263
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
 
2264
          ++errors;
 
2265
        }
 
2266
    }
 
2267
 
 
2268
  LT_DLMUTEX_UNLOCK ();
 
2269
 
 
2270
  return errors;
 
2271
}
 
2272
 
 
2273
int
 
2274
lt_dlpreload (preloaded)
 
2275
     const lt_dlsymlist *preloaded;
 
2276
{
 
2277
  int errors = 0;
 
2278
 
 
2279
  if (preloaded)
 
2280
    {
 
2281
      errors = presym_add_symlist (preloaded);
 
2282
    }
 
2283
  else
 
2284
    {
 
2285
      presym_free_symlists();
 
2286
 
 
2287
      LT_DLMUTEX_LOCK ();
 
2288
      if (default_preloaded_symbols)
 
2289
        {
 
2290
          errors = lt_dlpreload (default_preloaded_symbols);
 
2291
        }
 
2292
      LT_DLMUTEX_UNLOCK ();
 
2293
    }
 
2294
 
 
2295
  return errors;
 
2296
}
 
2297
 
 
2298
int
 
2299
lt_dlpreload_default (preloaded)
 
2300
     const lt_dlsymlist *preloaded;
 
2301
{
 
2302
  LT_DLMUTEX_LOCK ();
 
2303
  default_preloaded_symbols = preloaded;
 
2304
  LT_DLMUTEX_UNLOCK ();
 
2305
  return 0;
 
2306
}
 
2307
 
 
2308
int
 
2309
lt_dlexit ()
 
2310
{
 
2311
  /* shut down libltdl */
 
2312
  lt_dlloader *loader;
 
2313
  int          errors   = 0;
 
2314
 
 
2315
  LT_DLMUTEX_LOCK ();
 
2316
  loader = loaders;
 
2317
 
 
2318
  if (!initialized)
 
2319
    {
 
2320
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
 
2321
      ++errors;
 
2322
      goto done;
 
2323
    }
 
2324
 
 
2325
  /* shut down only at last call. */
 
2326
  if (--initialized == 0)
 
2327
    {
 
2328
      int       level;
 
2329
 
 
2330
      while (handles && LT_DLIS_RESIDENT (handles))
 
2331
        {
 
2332
          handles = handles->next;
 
2333
        }
 
2334
 
 
2335
      /* close all modules */
 
2336
      for (level = 1; handles; ++level)
 
2337
        {
 
2338
          lt_dlhandle cur = handles;
 
2339
          int saw_nonresident = 0;
 
2340
 
 
2341
          while (cur)
 
2342
            {
 
2343
              lt_dlhandle tmp = cur;
 
2344
              cur = cur->next;
 
2345
              if (!LT_DLIS_RESIDENT (tmp))
 
2346
                saw_nonresident = 1;
 
2347
              if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
 
2348
                {
 
2349
                  if (lt_dlclose (tmp))
 
2350
                    {
 
2351
                      ++errors;
 
2352
                    }
 
2353
                  /* Make sure that the handle pointed to by 'cur' still exists.
 
2354
                     lt_dlclose recursively closes dependent libraries which removes
 
2355
                     them from the linked list.  One of these might be the one
 
2356
                     pointed to by 'cur'.  */
 
2357
                  if (cur)
 
2358
                    {
 
2359
                      for (tmp = handles; tmp; tmp = tmp->next)
 
2360
                        if (tmp == cur)
 
2361
                          break;
 
2362
                      if (! tmp)
 
2363
                        cur = handles;
 
2364
                    }
 
2365
                }
 
2366
            }
 
2367
          /* done if only resident modules are left */
 
2368
          if (!saw_nonresident)
 
2369
            break;
 
2370
        }
 
2371
 
 
2372
      /* close all loaders */
 
2373
      while (loader)
 
2374
        {
 
2375
          lt_dlloader *next = loader->next;
 
2376
          lt_user_data data = loader->dlloader_data;
 
2377
          if (loader->dlloader_exit && loader->dlloader_exit (data))
 
2378
            {
 
2379
              ++errors;
 
2380
            }
 
2381
 
 
2382
          LT_DLMEM_REASSIGN (loader, next);
 
2383
        }
 
2384
      loaders = 0;
 
2385
    }
 
2386
 
 
2387
 done:
 
2388
  LT_DLMUTEX_UNLOCK ();
 
2389
  return errors;
 
2390
}
 
2391
 
 
2392
static int
 
2393
tryall_dlopen (handle, filename)
 
2394
     lt_dlhandle *handle;
 
2395
     const char *filename;
 
2396
{
 
2397
  lt_dlhandle    cur;
 
2398
  lt_dlloader   *loader;
 
2399
  const char    *saved_error;
 
2400
  int            errors         = 0;
 
2401
 
 
2402
  LT_DLMUTEX_GETERROR (saved_error);
 
2403
  LT_DLMUTEX_LOCK ();
 
2404
 
 
2405
  cur    = handles;
 
2406
  loader = loaders;
 
2407
 
 
2408
  /* check whether the module was already opened */
 
2409
  while (cur)
 
2410
    {
 
2411
      /* try to dlopen the program itself? */
 
2412
      if (!cur->info.filename && !filename)
 
2413
        {
 
2414
          break;
 
2415
        }
 
2416
 
 
2417
      if (cur->info.filename && filename
 
2418
          && strcmp (cur->info.filename, filename) == 0)
 
2419
        {
 
2420
          break;
 
2421
        }
 
2422
 
 
2423
      cur = cur->next;
 
2424
    }
 
2425
 
 
2426
  if (cur)
 
2427
    {
 
2428
      ++cur->info.ref_count;
 
2429
      *handle = cur;
 
2430
      goto done;
 
2431
    }
 
2432
 
 
2433
  cur = *handle;
 
2434
  if (filename)
 
2435
    {
 
2436
      /* Comment out the check of file permissions using access.
 
2437
         This call seems to always return -1 with error EACCES.
 
2438
      */
 
2439
      /* We need to catch missing file errors early so that
 
2440
         file_not_found() can detect what happened.
 
2441
      if (access (filename, R_OK) != 0)
 
2442
        {
 
2443
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
 
2444
          ++errors;
 
2445
          goto done;
 
2446
        } */
 
2447
 
 
2448
      cur->info.filename = lt_estrdup (filename);
 
2449
      if (!cur->info.filename)
 
2450
        {
 
2451
          ++errors;
 
2452
          goto done;
 
2453
        }
 
2454
    }
 
2455
  else
 
2456
    {
 
2457
      cur->info.filename = 0;
 
2458
    }
 
2459
 
 
2460
  while (loader)
 
2461
    {
 
2462
      lt_user_data data = loader->dlloader_data;
 
2463
 
 
2464
      cur->module = loader->module_open (data, filename);
 
2465
 
 
2466
      if (cur->module != 0)
 
2467
        {
 
2468
          break;
 
2469
        }
 
2470
      loader = loader->next;
 
2471
    }
 
2472
 
 
2473
  if (!loader)
 
2474
    {
 
2475
      LT_DLFREE (cur->info.filename);
 
2476
      ++errors;
 
2477
      goto done;
 
2478
    }
 
2479
 
 
2480
  cur->loader   = loader;
 
2481
  LT_DLMUTEX_SETERROR (saved_error);
 
2482
 
 
2483
 done:
 
2484
  LT_DLMUTEX_UNLOCK ();
 
2485
 
 
2486
  return errors;
 
2487
}
 
2488
 
 
2489
static int
 
2490
tryall_dlopen_module (handle, prefix, dirname, dlname)
 
2491
     lt_dlhandle *handle;
 
2492
     const char *prefix;
 
2493
     const char *dirname;
 
2494
     const char *dlname;
 
2495
{
 
2496
  int      error        = 0;
 
2497
  char     *filename    = 0;
 
2498
  size_t   filename_len = 0;
 
2499
  size_t   dirname_len  = LT_STRLEN (dirname);
 
2500
 
 
2501
  assert (handle);
 
2502
  assert (dirname);
 
2503
  assert (dlname);
 
2504
#ifdef LT_DIRSEP_CHAR
 
2505
  /* Only canonicalized names (i.e. with DIRSEP chars already converted)
 
2506
     should make it into this function:  */
 
2507
  assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
 
2508
#endif
 
2509
 
 
2510
  if (dirname_len > 0)
 
2511
    if (dirname[dirname_len -1] == '/')
 
2512
      --dirname_len;
 
2513
  filename_len = dirname_len + 1 + LT_STRLEN (dlname);
 
2514
 
 
2515
  /* Allocate memory, and combine DIRNAME and MODULENAME into it.
 
2516
     The PREFIX (if any) is handled below.  */
 
2517
  filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
 
2518
  if (!filename)
 
2519
    return 1;
 
2520
 
 
2521
  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
 
2522
 
 
2523
  /* Now that we have combined DIRNAME and MODULENAME, if there is
 
2524
     also a PREFIX to contend with, simply recurse with the arguments
 
2525
     shuffled.  Otherwise, attempt to open FILENAME as a module.  */
 
2526
  if (prefix)
 
2527
    {
 
2528
      error += tryall_dlopen_module (handle,
 
2529
                                     (const char *) 0, prefix, filename);
 
2530
    }
 
2531
  else if (tryall_dlopen (handle, filename) != 0)
 
2532
    {
 
2533
      ++error;
 
2534
    }
 
2535
 
 
2536
  LT_DLFREE (filename);
 
2537
  return error;
 
2538
}
 
2539
 
 
2540
static int
 
2541
find_module (handle, dir, libdir, dlname, old_name, installed)
 
2542
     lt_dlhandle *handle;
 
2543
     const char *dir;
 
2544
     const char *libdir;
 
2545
     const char *dlname;
 
2546
     const char *old_name;
 
2547
     int installed;
 
2548
{
 
2549
  /* Try to open the old library first; if it was dlpreopened,
 
2550
     we want the preopened version of it, even if a dlopenable
 
2551
     module is available.  */
 
2552
  if (old_name && tryall_dlopen (handle, old_name) == 0)
 
2553
    {
 
2554
      return 0;
 
2555
    }
 
2556
 
 
2557
  /* Try to open the dynamic library.  */
 
2558
  if (dlname)
 
2559
    {
 
2560
      /* try to open the installed module */
 
2561
      if (installed && libdir)
 
2562
        {
 
2563
          if (tryall_dlopen_module (handle,
 
2564
                                    (const char *) 0, libdir, dlname) == 0)
 
2565
            return 0;
 
2566
        }
 
2567
 
 
2568
      /* try to open the not-installed module */
 
2569
      if (!installed)
 
2570
        {
 
2571
          if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
 
2572
            return 0;
 
2573
        }
 
2574
 
 
2575
      /* maybe it was moved to another directory */
 
2576
      {
 
2577
          if (dir && (tryall_dlopen_module (handle,
 
2578
                                    (const char *) 0, dir, dlname) == 0))
 
2579
            return 0;
 
2580
      }
 
2581
    }
 
2582
 
 
2583
  return 1;
 
2584
}
 
2585
 
 
2586
 
 
2587
static int
 
2588
canonicalize_path (path, pcanonical)
 
2589
     const char *path;
 
2590
     char **pcanonical;
 
2591
{
 
2592
  char *canonical = 0;
 
2593
 
 
2594
  assert (path && *path);
 
2595
  assert (pcanonical);
 
2596
 
 
2597
  canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
 
2598
  if (!canonical)
 
2599
    return 1;
 
2600
 
 
2601
  {
 
2602
    size_t dest = 0;
 
2603
    size_t src;
 
2604
    for (src = 0; path[src] != LT_EOS_CHAR; ++src)
 
2605
      {
 
2606
        /* Path separators are not copied to the beginning or end of
 
2607
           the destination, or if another separator would follow
 
2608
           immediately.  */
 
2609
        if (path[src] == LT_PATHSEP_CHAR)
 
2610
          {
 
2611
            if ((dest == 0)
 
2612
                || (path[1+ src] == LT_PATHSEP_CHAR)
 
2613
                || (path[1+ src] == LT_EOS_CHAR))
 
2614
              continue;
 
2615
          }
 
2616
 
 
2617
        /* Anything other than a directory separator is copied verbatim.  */
 
2618
        if ((path[src] != '/')
 
2619
#ifdef LT_DIRSEP_CHAR
 
2620
            && (path[src] != LT_DIRSEP_CHAR)
 
2621
#endif
 
2622
            )
 
2623
          {
 
2624
            canonical[dest++] = path[src];
 
2625
          }
 
2626
        /* Directory separators are converted and copied only if they are
 
2627
           not at the end of a path -- i.e. before a path separator or
 
2628
           NULL terminator.  */
 
2629
        else if ((path[1+ src] != LT_PATHSEP_CHAR)
 
2630
                 && (path[1+ src] != LT_EOS_CHAR)
 
2631
#ifdef LT_DIRSEP_CHAR
 
2632
                 && (path[1+ src] != LT_DIRSEP_CHAR)
 
2633
#endif
 
2634
                 && (path[1+ src] != '/'))
 
2635
          {
 
2636
            canonical[dest++] = '/';
 
2637
          }
 
2638
      }
 
2639
 
 
2640
    /* Add an end-of-string marker at the end.  */
 
2641
    canonical[dest] = LT_EOS_CHAR;
 
2642
  }
 
2643
 
 
2644
  /* Assign new value.  */
 
2645
  *pcanonical = canonical;
 
2646
 
 
2647
  return 0;
 
2648
}
 
2649
 
 
2650
static int
 
2651
argzize_path (path, pargz, pargz_len)
 
2652
     const char *path;
 
2653
     char **pargz;
 
2654
     size_t *pargz_len;
 
2655
{
 
2656
  error_t error;
 
2657
 
 
2658
  assert (path);
 
2659
  assert (pargz);
 
2660
  assert (pargz_len);
 
2661
 
 
2662
  if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
 
2663
    {
 
2664
      switch (error)
 
2665
        {
 
2666
        case ENOMEM:
 
2667
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
 
2668
          break;
 
2669
        default:
 
2670
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
 
2671
          break;
 
2672
        }
 
2673
 
 
2674
      return 1;
 
2675
    }
 
2676
 
 
2677
  return 0;
 
2678
}
 
2679
 
 
2680
/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
 
2681
   of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
 
2682
   non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
 
2683
   it is appended to each SEARCH_PATH element before FUNC is called.  */
 
2684
static int
 
2685
foreach_dirinpath (search_path, base_name, func, data1, data2)
 
2686
     const char *search_path;
 
2687
     const char *base_name;
 
2688
     foreach_callback_func *func;
 
2689
     lt_ptr data1;
 
2690
     lt_ptr data2;
 
2691
{
 
2692
  int    result         = 0;
 
2693
  int    filenamesize   = 0;
 
2694
  size_t lenbase        = LT_STRLEN (base_name);
 
2695
  size_t argz_len       = 0;
 
2696
  char *argz            = 0;
 
2697
  char *filename        = 0;
 
2698
  char *canonical       = 0;
 
2699
 
 
2700
  LT_DLMUTEX_LOCK ();
 
2701
 
 
2702
  if (!search_path || !*search_path)
 
2703
    {
 
2704
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
 
2705
      goto cleanup;
 
2706
    }
 
2707
 
 
2708
  if (canonicalize_path (search_path, &canonical) != 0)
 
2709
    goto cleanup;
 
2710
 
 
2711
  if (argzize_path (canonical, &argz, &argz_len) != 0)
 
2712
    goto cleanup;
 
2713
 
 
2714
  {
 
2715
    char *dir_name = 0;
 
2716
    while ((dir_name = argz_next (argz, argz_len, dir_name)))
 
2717
      {
 
2718
        size_t lendir = LT_STRLEN (dir_name);
 
2719
 
 
2720
        if (lendir +1 +lenbase >= filenamesize)
 
2721
        {
 
2722
          LT_DLFREE (filename);
 
2723
          filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
 
2724
          filename      = LT_EMALLOC (char, filenamesize);
 
2725
          if (!filename)
 
2726
            goto cleanup;
 
2727
        }
 
2728
 
 
2729
        assert (filenamesize > lendir);
 
2730
        strcpy (filename, dir_name);
 
2731
 
 
2732
        if (base_name && *base_name)
 
2733
          {
 
2734
            if (filename[lendir -1] != '/')
 
2735
              filename[lendir++] = '/';
 
2736
            strcpy (filename +lendir, base_name);
 
2737
          }
 
2738
 
 
2739
        if ((result = (*func) (filename, data1, data2)))
 
2740
          {
 
2741
            break;
 
2742
          }
 
2743
      }
 
2744
  }
 
2745
 
 
2746
 cleanup:
 
2747
  LT_DLFREE (argz);
 
2748
  LT_DLFREE (canonical);
 
2749
  LT_DLFREE (filename);
 
2750
 
 
2751
  LT_DLMUTEX_UNLOCK ();
 
2752
 
 
2753
  return result;
 
2754
}
 
2755
 
 
2756
/* If FILEPATH can be opened, store the name of the directory component
 
2757
   in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
 
2758
   DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
 
2759
static int
 
2760
find_file_callback (filename, data1, data2)
 
2761
     char *filename;
 
2762
     lt_ptr data1;
 
2763
     lt_ptr data2;
 
2764
{
 
2765
  char       **pdir     = (char **) data1;
 
2766
  FILE       **pfile    = (FILE **) data2;
 
2767
  int        is_done    = 0;
 
2768
 
 
2769
  assert (filename && *filename);
 
2770
  assert (pdir);
 
2771
  assert (pfile);
 
2772
 
 
2773
  if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
 
2774
    {
 
2775
      char *dirend = strrchr (filename, '/');
 
2776
 
 
2777
      if (dirend > filename)
 
2778
        *dirend   = LT_EOS_CHAR;
 
2779
 
 
2780
      LT_DLFREE (*pdir);
 
2781
      *pdir   = lt_estrdup (filename);
 
2782
      is_done = (*pdir == 0) ? -1 : 1;
 
2783
    }
 
2784
 
 
2785
  return is_done;
 
2786
}
 
2787
 
 
2788
static FILE *
 
2789
find_file (search_path, base_name, pdir)
 
2790
     const char *search_path;
 
2791
     const char *base_name;
 
2792
     char **pdir;
 
2793
{
 
2794
  FILE *file = 0;
 
2795
 
 
2796
  foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
 
2797
 
 
2798
  return file;
 
2799
}
 
2800
 
 
2801
static int
 
2802
find_handle_callback (filename, data, ignored)
 
2803
     char *filename;
 
2804
     lt_ptr data;
 
2805
     lt_ptr ignored;
 
2806
{
 
2807
  lt_dlhandle  *handle          = (lt_dlhandle *) data;
 
2808
  int           notfound        = access (filename, R_OK);
 
2809
 
 
2810
  /* Bail out if file cannot be read...  */
 
2811
  if (notfound)
 
2812
    return 0;
 
2813
 
 
2814
  /* Try to dlopen the file, but do not continue searching in any
 
2815
     case.  */
 
2816
  if (tryall_dlopen (handle, filename) != 0)
 
2817
    *handle = 0;
 
2818
 
 
2819
  return 1;
 
2820
}
 
2821
 
 
2822
/* If HANDLE was found return it, otherwise return 0.  If HANDLE was
 
2823
   found but could not be opened, *HANDLE will be set to 0.  */
 
2824
static lt_dlhandle *
 
2825
find_handle (search_path, base_name, handle)
 
2826
     const char *search_path;
 
2827
     const char *base_name;
 
2828
     lt_dlhandle *handle;
 
2829
{
 
2830
  if (!search_path)
 
2831
    return 0;
 
2832
 
 
2833
  if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
 
2834
                          handle, 0))
 
2835
    return 0;
 
2836
 
 
2837
  return handle;
 
2838
}
 
2839
 
 
2840
static int
 
2841
load_deplibs (handle, deplibs)
 
2842
     lt_dlhandle handle;
 
2843
     char *deplibs;
 
2844
{
 
2845
#if LTDL_DLOPEN_DEPLIBS
 
2846
  char  *p, *save_search_path = 0;
 
2847
  int   depcount = 0;
 
2848
  int   i;
 
2849
  char  **names = 0;
 
2850
#endif
 
2851
  int   errors = 0;
 
2852
 
 
2853
  handle->depcount = 0;
 
2854
 
 
2855
#if LTDL_DLOPEN_DEPLIBS
 
2856
  if (!deplibs)
 
2857
    {
 
2858
      return errors;
 
2859
    }
 
2860
  ++errors;
 
2861
 
 
2862
  LT_DLMUTEX_LOCK ();
 
2863
  if (user_search_path)
 
2864
    {
 
2865
      save_search_path = lt_estrdup (user_search_path);
 
2866
      if (!save_search_path)
 
2867
        goto cleanup;
 
2868
    }
 
2869
 
 
2870
  /* extract search paths and count deplibs */
 
2871
  p = deplibs;
 
2872
  while (*p)
 
2873
    {
 
2874
      if (!isspace ((int) *p))
 
2875
        {
 
2876
          char *end = p+1;
 
2877
          while (*end && !isspace((int) *end))
 
2878
            {
 
2879
              ++end;
 
2880
            }
 
2881
 
 
2882
          if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
 
2883
            {
 
2884
              char save = *end;
 
2885
              *end = 0; /* set a temporary string terminator */
 
2886
              if (lt_dladdsearchdir(p+2))
 
2887
                {
 
2888
                  goto cleanup;
 
2889
                }
 
2890
              *end = save;
 
2891
            }
 
2892
          else
 
2893
            {
 
2894
              ++depcount;
 
2895
            }
 
2896
 
 
2897
          p = end;
 
2898
        }
 
2899
      else
 
2900
        {
 
2901
          ++p;
 
2902
        }
 
2903
    }
 
2904
 
 
2905
  if (!depcount)
 
2906
    {
 
2907
      errors = 0;
 
2908
      goto cleanup;
 
2909
    }
 
2910
 
 
2911
  names = LT_EMALLOC (char *, depcount * sizeof (char*));
 
2912
  if (!names)
 
2913
    goto cleanup;
 
2914
 
 
2915
  /* now only extract the actual deplibs */
 
2916
  depcount = 0;
 
2917
  p = deplibs;
 
2918
  while (*p)
 
2919
    {
 
2920
      if (isspace ((int) *p))
 
2921
        {
 
2922
          ++p;
 
2923
        }
 
2924
      else
 
2925
        {
 
2926
          char *end = p+1;
 
2927
          while (*end && !isspace ((int) *end))
 
2928
            {
 
2929
              ++end;
 
2930
            }
 
2931
 
 
2932
          if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
 
2933
            {
 
2934
              char *name;
 
2935
              char save = *end;
 
2936
              *end = 0; /* set a temporary string terminator */
 
2937
              if (strncmp(p, "-l", 2) == 0)
 
2938
                {
 
2939
                  size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
 
2940
                  name = LT_EMALLOC (char, 1+ name_len);
 
2941
                  if (name)
 
2942
                    sprintf (name, "lib%s", p+2);
 
2943
                }
 
2944
              else
 
2945
                name = lt_estrdup(p);
 
2946
 
 
2947
              if (!name)
 
2948
                goto cleanup_names;
 
2949
 
 
2950
              names[depcount++] = name;
 
2951
              *end = save;
 
2952
            }
 
2953
          p = end;
 
2954
        }
 
2955
    }
 
2956
 
 
2957
  /* load the deplibs (in reverse order)
 
2958
     At this stage, don't worry if the deplibs do not load correctly,
 
2959
     they may already be statically linked into the loading application
 
2960
     for instance.  There will be a more enlightening error message
 
2961
     later on if the loaded module cannot resolve all of its symbols.  */
 
2962
  if (depcount)
 
2963
    {
 
2964
      int       j = 0;
 
2965
 
 
2966
      handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
 
2967
      if (!handle->deplibs)
 
2968
        goto cleanup_names;
 
2969
 
 
2970
      for (i = 0; i < depcount; ++i)
 
2971
        {
 
2972
          handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
 
2973
          if (handle->deplibs[j])
 
2974
            {
 
2975
              ++j;
 
2976
            }
 
2977
        }
 
2978
 
 
2979
      handle->depcount  = j;    /* Number of successfully loaded deplibs */
 
2980
      errors            = 0;
 
2981
    }
 
2982
 
 
2983
 cleanup_names:
 
2984
  for (i = 0; i < depcount; ++i)
 
2985
    {
 
2986
      LT_DLFREE (names[i]);
 
2987
    }
 
2988
 
 
2989
 cleanup:
 
2990
  LT_DLFREE (names);
 
2991
  /* restore the old search path */
 
2992
  if (user_search_path) {
 
2993
    LT_DLFREE (user_search_path);
 
2994
    user_search_path = save_search_path;
 
2995
  }
 
2996
  LT_DLMUTEX_UNLOCK ();
 
2997
 
 
2998
#endif
 
2999
 
 
3000
  return errors;
 
3001
}
 
3002
 
 
3003
static int
 
3004
unload_deplibs (handle)
 
3005
     lt_dlhandle handle;
 
3006
{
 
3007
  int i;
 
3008
  int errors = 0;
 
3009
 
 
3010
  if (handle->depcount)
 
3011
    {
 
3012
      for (i = 0; i < handle->depcount; ++i)
 
3013
        {
 
3014
          if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
 
3015
            {
 
3016
              errors += lt_dlclose (handle->deplibs[i]);
 
3017
            }
 
3018
        }
 
3019
      LT_DLFREE (handle->deplibs);
 
3020
    }
 
3021
 
 
3022
  return errors;
 
3023
}
 
3024
 
 
3025
static int
 
3026
trim (dest, str)
 
3027
     char **dest;
 
3028
     const char *str;
 
3029
{
 
3030
  /* remove the leading and trailing "'" from str
 
3031
     and store the result in dest */
 
3032
  const char *end   = strrchr (str, '\'');
 
3033
  size_t len        = LT_STRLEN (str);
 
3034
  char *tmp;
 
3035
 
 
3036
  LT_DLFREE (*dest);
 
3037
 
 
3038
  if (!end)
 
3039
    return 1;
 
3040
 
 
3041
  if (len > 3 && str[0] == '\'')
 
3042
    {
 
3043
      tmp = LT_EMALLOC (char, end - str);
 
3044
      if (!tmp)
 
3045
        return 1;
 
3046
 
 
3047
      strncpy(tmp, &str[1], (end - str) - 1);
 
3048
      tmp[(end - str) - 1] = LT_EOS_CHAR;
 
3049
      *dest = tmp;
 
3050
    }
 
3051
  else
 
3052
    {
 
3053
      *dest = 0;
 
3054
    }
 
3055
 
 
3056
  return 0;
 
3057
}
 
3058
 
 
3059
static int
 
3060
free_vars (dlname, oldname, libdir, deplibs)
 
3061
     char *dlname;
 
3062
     char *oldname;
 
3063
     char *libdir;
 
3064
     char *deplibs;
 
3065
{
 
3066
  LT_DLFREE (dlname);
 
3067
  LT_DLFREE (oldname);
 
3068
  LT_DLFREE (libdir);
 
3069
  LT_DLFREE (deplibs);
 
3070
 
 
3071
  return 0;
 
3072
}
 
3073
 
 
3074
static int
 
3075
try_dlopen (phandle, filename)
 
3076
     lt_dlhandle *phandle;
 
3077
     const char *filename;
 
3078
{
 
3079
  const char *  ext             = 0;
 
3080
  const char *  saved_error     = 0;
 
3081
  char *        canonical       = 0;
 
3082
  char *        base_name       = 0;
 
3083
  char *        dir             = 0;
 
3084
  char *        name            = 0;
 
3085
  int           errors          = 0;
 
3086
  lt_dlhandle   newhandle;
 
3087
 
 
3088
  assert (phandle);
 
3089
  assert (*phandle == 0);
 
3090
 
 
3091
  LT_DLMUTEX_GETERROR (saved_error);
 
3092
 
 
3093
  /* dlopen self? */
 
3094
  if (!filename)
 
3095
    {
 
3096
      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
 
3097
      if (*phandle == 0)
 
3098
        return 1;
 
3099
 
 
3100
      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
 
3101
      newhandle = *phandle;
 
3102
 
 
3103
      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
 
3104
      LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
 
3105
 
 
3106
      if (tryall_dlopen (&newhandle, 0) != 0)
 
3107
        {
 
3108
          LT_DLFREE (*phandle);
 
3109
          return 1;
 
3110
        }
 
3111
 
 
3112
      goto register_handle;
 
3113
    }
 
3114
 
 
3115
  assert (filename && *filename);
 
3116
 
 
3117
  /* Doing this immediately allows internal functions to safely
 
3118
     assume only canonicalized paths are passed.  */
 
3119
  if (canonicalize_path (filename, &canonical) != 0)
 
3120
    {
 
3121
      ++errors;
 
3122
      goto cleanup;
 
3123
    }
 
3124
 
 
3125
  /* If the canonical module name is a path (relative or absolute)
 
3126
     then split it into a directory part and a name part.  */
 
3127
  base_name = strrchr (canonical, '/');
 
3128
  if (base_name)
 
3129
    {
 
3130
      size_t dirlen = (1+ base_name) - canonical;
 
3131
 
 
3132
      dir = LT_EMALLOC (char, 1+ dirlen);
 
3133
      if (!dir)
 
3134
        {
 
3135
          ++errors;
 
3136
          goto cleanup;
 
3137
        }
 
3138
 
 
3139
      strncpy (dir, canonical, dirlen);
 
3140
      dir[dirlen] = LT_EOS_CHAR;
 
3141
 
 
3142
      ++base_name;
 
3143
    }
 
3144
  else
 
3145
    base_name = canonical;
 
3146
 
 
3147
  assert (base_name && *base_name);
 
3148
 
 
3149
  /* Check whether we are opening a libtool module (.la extension).  */
 
3150
  ext = strrchr (base_name, '.');
 
3151
  if (ext && strcmp (ext, archive_ext) == 0)
 
3152
    {
 
3153
      /* this seems to be a libtool module */
 
3154
      FILE *    file     = 0;
 
3155
      char *    dlname   = 0;
 
3156
      char *    old_name = 0;
 
3157
      char *    libdir   = 0;
 
3158
      char *    deplibs  = 0;
 
3159
      char *    line     = 0;
 
3160
      size_t    line_len;
 
3161
 
 
3162
      /* if we can't find the installed flag, it is probably an
 
3163
         installed libtool archive, produced with an old version
 
3164
         of libtool */
 
3165
      int       installed = 1;
 
3166
 
 
3167
      /* extract the module name from the file name */
 
3168
      name = LT_EMALLOC (char, ext - base_name + 1);
 
3169
      if (!name)
 
3170
        {
 
3171
          ++errors;
 
3172
          goto cleanup;
 
3173
        }
 
3174
 
 
3175
      /* canonicalize the module name */
 
3176
      {
 
3177
        size_t i;
 
3178
        for (i = 0; i < ext - base_name; ++i)
 
3179
          {
 
3180
            if (isalnum ((int)(base_name[i])))
 
3181
              {
 
3182
                name[i] = base_name[i];
 
3183
              }
 
3184
            else
 
3185
              {
 
3186
                name[i] = '_';
 
3187
              }
 
3188
          }
 
3189
        name[ext - base_name] = LT_EOS_CHAR;
 
3190
      }
 
3191
 
 
3192
      /* Now try to open the .la file.  If there is no directory name
 
3193
         component, try to find it first in user_search_path and then other
 
3194
         prescribed paths.  Otherwise (or in any case if the module was not
 
3195
         yet found) try opening just the module name as passed.  */
 
3196
      if (!dir)
 
3197
        {
 
3198
          const char *search_path;
 
3199
 
 
3200
          LT_DLMUTEX_LOCK ();
 
3201
          search_path = user_search_path;
 
3202
          if (search_path)
 
3203
            file = find_file (user_search_path, base_name, &dir);
 
3204
          LT_DLMUTEX_UNLOCK ();
 
3205
 
 
3206
          if (!file)
 
3207
            {
 
3208
              search_path = getenv (LTDL_SEARCHPATH_VAR);
 
3209
              if (search_path)
 
3210
                file = find_file (search_path, base_name, &dir);
 
3211
            }
 
3212
 
 
3213
#ifdef LTDL_SHLIBPATH_VAR
 
3214
          if (!file)
 
3215
            {
 
3216
              search_path = getenv (LTDL_SHLIBPATH_VAR);
 
3217
              if (search_path)
 
3218
                file = find_file (search_path, base_name, &dir);
 
3219
            }
 
3220
#endif
 
3221
#ifdef LTDL_SYSSEARCHPATH
 
3222
          if (!file && *sys_search_path)
 
3223
            {
 
3224
              file = find_file (sys_search_path, base_name, &dir);
 
3225
            }
 
3226
#endif
 
3227
        }
 
3228
      if (!file)
 
3229
        {
 
3230
          file = fopen (filename, LT_READTEXT_MODE);
 
3231
        }
 
3232
 
 
3233
      /* If we didn't find the file by now, it really isn't there.  Set
 
3234
         the status flag, and bail out.  */
 
3235
      if (!file)
 
3236
        {
 
3237
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
 
3238
          ++errors;
 
3239
          goto cleanup;
 
3240
        }
 
3241
 
 
3242
      line_len = LT_FILENAME_MAX;
 
3243
      line = LT_EMALLOC (char, line_len);
 
3244
      if (!line)
 
3245
        {
 
3246
          fclose (file);
 
3247
          ++errors;
 
3248
          goto cleanup;
 
3249
        }
 
3250
 
 
3251
      /* read the .la file */
 
3252
      while (!feof (file))
 
3253
        {
 
3254
          line[line_len-2] = '\0';
 
3255
          if (!fgets (line, (int) line_len, file))
 
3256
            {
 
3257
              break;
 
3258
            }
 
3259
 
 
3260
          /* Handle the case where we occasionally need to read a line
 
3261
             that is longer than the initial buffer size.
 
3262
             Behave even if the file contains NUL bytes due to corruption. */
 
3263
          while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
 
3264
            {
 
3265
              line = LT_DLREALLOC (char, line, line_len *2);
 
3266
              line[line_len*2 - 2] = '\0';
 
3267
              if (!fgets (&line[line_len -1], (int) line_len +1, file))
 
3268
                {
 
3269
                  break;
 
3270
                }
 
3271
              line_len *= 2;
 
3272
            }
 
3273
 
 
3274
          if (line[0] == '\n' || line[0] == '#')
 
3275
            {
 
3276
              continue;
 
3277
            }
 
3278
 
 
3279
#undef  STR_DLNAME
 
3280
#define STR_DLNAME      "dlname="
 
3281
          if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
 
3282
            {
 
3283
              errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
 
3284
            }
 
3285
 
 
3286
#undef  STR_OLD_LIBRARY
 
3287
#define STR_OLD_LIBRARY "old_library="
 
3288
          else if (strncmp (line, STR_OLD_LIBRARY,
 
3289
                            sizeof (STR_OLD_LIBRARY) - 1) == 0)
 
3290
            {
 
3291
              errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
 
3292
            }
 
3293
#undef  STR_LIBDIR
 
3294
#define STR_LIBDIR      "libdir="
 
3295
          else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
 
3296
            {
 
3297
              errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
 
3298
            }
 
3299
 
 
3300
#undef  STR_DL_DEPLIBS
 
3301
#define STR_DL_DEPLIBS  "dependency_libs="
 
3302
          else if (strncmp (line, STR_DL_DEPLIBS,
 
3303
                            sizeof (STR_DL_DEPLIBS) - 1) == 0)
 
3304
            {
 
3305
              errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
 
3306
            }
 
3307
          else if (strcmp (line, "installed=yes\n") == 0)
 
3308
            {
 
3309
              installed = 1;
 
3310
            }
 
3311
          else if (strcmp (line, "installed=no\n") == 0)
 
3312
            {
 
3313
              installed = 0;
 
3314
            }
 
3315
 
 
3316
#undef  STR_LIBRARY_NAMES
 
3317
#define STR_LIBRARY_NAMES "library_names="
 
3318
          else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
 
3319
                                        sizeof (STR_LIBRARY_NAMES) - 1) == 0)
 
3320
            {
 
3321
              char *last_libname;
 
3322
              errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
 
3323
              if (!errors
 
3324
                  && dlname
 
3325
                  && (last_libname = strrchr (dlname, ' ')) != 0)
 
3326
                {
 
3327
                  last_libname = lt_estrdup (last_libname + 1);
 
3328
                  if (!last_libname)
 
3329
                    {
 
3330
                      ++errors;
 
3331
                      goto cleanup;
 
3332
                    }
 
3333
                  LT_DLMEM_REASSIGN (dlname, last_libname);
 
3334
                }
 
3335
            }
 
3336
 
 
3337
          if (errors)
 
3338
            break;
 
3339
        }
 
3340
 
 
3341
      fclose (file);
 
3342
      LT_DLFREE (line);
 
3343
 
 
3344
      /* allocate the handle */
 
3345
      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
 
3346
      if (*phandle == 0)
 
3347
        ++errors;
 
3348
 
 
3349
      if (errors)
 
3350
        {
 
3351
          free_vars (dlname, old_name, libdir, deplibs);
 
3352
          LT_DLFREE (*phandle);
 
3353
          goto cleanup;
 
3354
        }
 
3355
 
 
3356
      assert (*phandle);
 
3357
 
 
3358
      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
 
3359
      if (load_deplibs (*phandle, deplibs) == 0)
 
3360
        {
 
3361
          newhandle = *phandle;
 
3362
          /* find_module may replace newhandle */
 
3363
          if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
 
3364
            {
 
3365
              unload_deplibs (*phandle);
 
3366
              ++errors;
 
3367
            }
 
3368
        }
 
3369
      else
 
3370
        {
 
3371
          ++errors;
 
3372
        }
 
3373
 
 
3374
      free_vars (dlname, old_name, libdir, deplibs);
 
3375
      if (errors)
 
3376
        {
 
3377
          LT_DLFREE (*phandle);
 
3378
          goto cleanup;
 
3379
        }
 
3380
 
 
3381
      if (*phandle != newhandle)
 
3382
        {
 
3383
          unload_deplibs (*phandle);
 
3384
        }
 
3385
    }
 
3386
  else
 
3387
    {
 
3388
      /* not a libtool module */
 
3389
      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
 
3390
      if (*phandle == 0)
 
3391
        {
 
3392
          ++errors;
 
3393
          goto cleanup;
 
3394
        }
 
3395
 
 
3396
      memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
 
3397
      newhandle = *phandle;
 
3398
 
 
3399
      /* If the module has no directory name component, try to find it
 
3400
         first in user_search_path and then other prescribed paths.
 
3401
         Otherwise (or in any case if the module was not yet found) try
 
3402
         opening just the module name as passed.  */
 
3403
      if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
 
3404
                   && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
 
3405
                                    &newhandle)
 
3406
#ifdef LTDL_SHLIBPATH_VAR
 
3407
                   && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
 
3408
                                    &newhandle)
 
3409
#endif
 
3410
#ifdef LTDL_SYSSEARCHPATH
 
3411
                   && !find_handle (sys_search_path, base_name, &newhandle)
 
3412
#endif
 
3413
                   )))
 
3414
        {
 
3415
          if (tryall_dlopen (&newhandle, filename) != 0)
 
3416
            {
 
3417
              newhandle = NULL;
 
3418
            }
 
3419
        }
 
3420
 
 
3421
      if (!newhandle)
 
3422
        {
 
3423
          LT_DLFREE (*phandle);
 
3424
          ++errors;
 
3425
          goto cleanup;
 
3426
        }
 
3427
    }
 
3428
 
 
3429
 register_handle:
 
3430
  LT_DLMEM_REASSIGN (*phandle, newhandle);
 
3431
 
 
3432
  if ((*phandle)->info.ref_count == 0)
 
3433
    {
 
3434
      (*phandle)->info.ref_count        = 1;
 
3435
      LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
 
3436
 
 
3437
      LT_DLMUTEX_LOCK ();
 
3438
      (*phandle)->next          = handles;
 
3439
      handles                   = *phandle;
 
3440
      LT_DLMUTEX_UNLOCK ();
 
3441
    }
 
3442
 
 
3443
  LT_DLMUTEX_SETERROR (saved_error);
 
3444
 
 
3445
 cleanup:
 
3446
  LT_DLFREE (dir);
 
3447
  LT_DLFREE (name);
 
3448
  LT_DLFREE (canonical);
 
3449
 
 
3450
  return errors;
 
3451
}
 
3452
 
 
3453
lt_dlhandle
 
3454
lt_dlopen (filename)
 
3455
     const char *filename;
 
3456
{
 
3457
  lt_dlhandle handle = 0;
 
3458
 
 
3459
  /* Just incase we missed a code path in try_dlopen() that reports
 
3460
     an error, but forgets to reset handle... */
 
3461
  if (try_dlopen (&handle, filename) != 0)
 
3462
    return 0;
 
3463
 
 
3464
  return handle;
 
3465
}
 
3466
 
 
3467
/* If the last error messge store was `FILE_NOT_FOUND', then return
 
3468
   non-zero.  */
 
3469
static int
 
3470
file_not_found ()
 
3471
{
 
3472
  const char *error = 0;
 
3473
 
 
3474
  LT_DLMUTEX_GETERROR (error);
 
3475
  if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
 
3476
    return 1;
 
3477
 
 
3478
  return 0;
 
3479
}
 
3480
 
 
3481
/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
 
3482
   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
 
3483
   and if a file is still not found try again with SHLIB_EXT appended
 
3484
   instead.  */
 
3485
lt_dlhandle
 
3486
lt_dlopenext (filename)
 
3487
     const char *filename;
 
3488
{
 
3489
  lt_dlhandle   handle          = 0;
 
3490
  char *        tmp             = 0;
 
3491
  char *        ext             = 0;
 
3492
  size_t        len;
 
3493
  int           errors          = 0;
 
3494
 
 
3495
  if (!filename)
 
3496
    {
 
3497
      return lt_dlopen (filename);
 
3498
    }
 
3499
 
 
3500
  assert (filename);
 
3501
 
 
3502
  len = LT_STRLEN (filename);
 
3503
  ext = strrchr (filename, '.');
 
3504
 
 
3505
  /* If FILENAME already bears a suitable extension, there is no need
 
3506
     to try appending additional extensions.  */
 
3507
  if (ext && ((strcmp (ext, archive_ext) == 0)
 
3508
#ifdef LTDL_SHLIB_EXT
 
3509
              || (strcmp (ext, shlib_ext) == 0)
 
3510
#endif
 
3511
      ))
 
3512
    {
 
3513
      return lt_dlopen (filename);
 
3514
    }
 
3515
 
 
3516
  /* First try appending ARCHIVE_EXT.  */
 
3517
  tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
 
3518
  if (!tmp)
 
3519
    return 0;
 
3520
 
 
3521
  strcpy (tmp, filename);
 
3522
  strcat (tmp, archive_ext);
 
3523
  errors = try_dlopen (&handle, tmp);
 
3524
 
 
3525
  /* If we found FILENAME, stop searching -- whether we were able to
 
3526
     load the file as a module or not.  If the file exists but loading
 
3527
     failed, it is better to return an error message here than to
 
3528
     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
 
3529
     in the module search path.  */
 
3530
  if (handle || ((errors > 0) && !file_not_found ()))
 
3531
    {
 
3532
      LT_DLFREE (tmp);
 
3533
      return handle;
 
3534
    }
 
3535
 
 
3536
#ifdef LTDL_SHLIB_EXT
 
3537
  /* Try appending SHLIB_EXT.   */
 
3538
  if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
 
3539
    {
 
3540
      LT_DLFREE (tmp);
 
3541
      tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
 
3542
      if (!tmp)
 
3543
        return 0;
 
3544
 
 
3545
      strcpy (tmp, filename);
 
3546
    }
 
3547
  else
 
3548
    {
 
3549
      tmp[len] = LT_EOS_CHAR;
 
3550
    }
 
3551
 
 
3552
  strcat(tmp, shlib_ext);
 
3553
  errors = try_dlopen (&handle, tmp);
 
3554
 
 
3555
  /* As before, if the file was found but loading failed, return now
 
3556
     with the current error message.  */
 
3557
  if (handle || ((errors > 0) && !file_not_found ()))
 
3558
    {
 
3559
      LT_DLFREE (tmp);
 
3560
      return handle;
 
3561
    }
 
3562
#endif
 
3563
 
 
3564
  /* Still here?  Then we really did fail to locate any of the file
 
3565
     names we tried.  */
 
3566
  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
 
3567
  LT_DLFREE (tmp);
 
3568
  return 0;
 
3569
}
 
3570
 
 
3571
 
 
3572
static int
 
3573
lt_argz_insert (pargz, pargz_len, before, entry)
 
3574
     char **pargz;
 
3575
     size_t *pargz_len;
 
3576
     char *before;
 
3577
     const char *entry;
 
3578
{
 
3579
  error_t error;
 
3580
 
 
3581
  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
 
3582
     pargz_len, NULL, entry) failed with EINVAL.  */
 
3583
  if (before)
 
3584
    error = argz_insert (pargz, pargz_len, before, entry);
 
3585
  else
 
3586
    error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
 
3587
 
 
3588
  if (error)
 
3589
    {
 
3590
      switch (error)
 
3591
        {
 
3592
        case ENOMEM:
 
3593
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
 
3594
          break;
 
3595
        default:
 
3596
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
 
3597
          break;
 
3598
        }
 
3599
      return 1;
 
3600
    }
 
3601
 
 
3602
  return 0;
 
3603
}
 
3604
 
 
3605
static int
 
3606
lt_argz_insertinorder (pargz, pargz_len, entry)
 
3607
     char **pargz;
 
3608
     size_t *pargz_len;
 
3609
     const char *entry;
 
3610
{
 
3611
  char *before = 0;
 
3612
 
 
3613
  assert (pargz);
 
3614
  assert (pargz_len);
 
3615
  assert (entry && *entry);
 
3616
 
 
3617
  if (*pargz)
 
3618
    while ((before = argz_next (*pargz, *pargz_len, before)))
 
3619
      {
 
3620
        int cmp = strcmp (entry, before);
 
3621
 
 
3622
        if (cmp < 0)  break;
 
3623
        if (cmp == 0) return 0; /* No duplicates! */
 
3624
      }
 
3625
 
 
3626
  return lt_argz_insert (pargz, pargz_len, before, entry);
 
3627
}
 
3628
 
 
3629
static int
 
3630
lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
 
3631
     char **pargz;
 
3632
     size_t *pargz_len;
 
3633
     const char *dirnam;
 
3634
     struct dirent *dp;
 
3635
{
 
3636
  char   *buf       = 0;
 
3637
  size_t buf_len    = 0;
 
3638
  char   *end       = 0;
 
3639
  size_t end_offset = 0;
 
3640
  size_t dir_len    = 0;
 
3641
  int    errors     = 0;
 
3642
 
 
3643
  assert (pargz);
 
3644
  assert (pargz_len);
 
3645
  assert (dp);
 
3646
 
 
3647
  dir_len = LT_STRLEN (dirnam);
 
3648
  end     = dp->d_name + LT_D_NAMLEN(dp);
 
3649
 
 
3650
  /* Ignore version numbers.  */
 
3651
  {
 
3652
    char *p;
 
3653
    for (p = end; p -1 > dp->d_name; --p)
 
3654
      if (strchr (".0123456789", p[-1]) == 0)
 
3655
        break;
 
3656
 
 
3657
    if (*p == '.')
 
3658
      end = p;
 
3659
  }
 
3660
 
 
3661
  /* Ignore filename extension.  */
 
3662
  {
 
3663
    char *p;
 
3664
    for (p = end -1; p > dp->d_name; --p)
 
3665
      if (*p == '.')
 
3666
        {
 
3667
          end = p;
 
3668
          break;
 
3669
        }
 
3670
  }
 
3671
 
 
3672
  /* Prepend the directory name.  */
 
3673
  end_offset    = end - dp->d_name;
 
3674
  buf_len       = dir_len + 1+ end_offset;
 
3675
  buf           = LT_EMALLOC (char, 1+ buf_len);
 
3676
  if (!buf)
 
3677
    return ++errors;
 
3678
 
 
3679
  assert (buf);
 
3680
 
 
3681
  strcpy  (buf, dirnam);
 
3682
  strcat  (buf, "/");
 
3683
  strncat (buf, dp->d_name, end_offset);
 
3684
  buf[buf_len] = LT_EOS_CHAR;
 
3685
 
 
3686
  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
 
3687
  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
 
3688
    ++errors;
 
3689
 
 
3690
  LT_DLFREE (buf);
 
3691
 
 
3692
  return errors;
 
3693
}
 
3694
 
 
3695
static int
 
3696
list_files_by_dir (dirnam, pargz, pargz_len)
 
3697
     const char *dirnam;
 
3698
     char **pargz;
 
3699
     size_t *pargz_len;
 
3700
{
 
3701
  DIR   *dirp     = 0;
 
3702
  int    errors   = 0;
 
3703
 
 
3704
  assert (dirnam && *dirnam);
 
3705
  assert (pargz);
 
3706
  assert (pargz_len);
 
3707
  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
 
3708
 
 
3709
  dirp = opendir (dirnam);
 
3710
  if (dirp)
 
3711
    {
 
3712
      struct dirent *dp = 0;
 
3713
 
 
3714
      while ((dp = readdir (dirp)))
 
3715
        if (dp->d_name[0] != '.')
 
3716
          if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
 
3717
            {
 
3718
              ++errors;
 
3719
              break;
 
3720
            }
 
3721
 
 
3722
      closedir (dirp);
 
3723
    }
 
3724
  else
 
3725
    ++errors;
 
3726
 
 
3727
  return errors;
 
3728
}
 
3729
 
 
3730
 
 
3731
/* If there are any files in DIRNAME, call the function passed in
 
3732
   DATA1 (with the name of each file and DATA2 as arguments).  */
 
3733
static int
 
3734
foreachfile_callback (dirname, data1, data2)
 
3735
     char *dirname;
 
3736
     lt_ptr data1;
 
3737
     lt_ptr data2;
 
3738
{
 
3739
  file_worker_func *func = *(file_worker_func **) data1;
 
3740
 
 
3741
  int     is_done  = 0;
 
3742
  char   *argz     = 0;
 
3743
  size_t  argz_len = 0;
 
3744
 
 
3745
  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
 
3746
    goto cleanup;
 
3747
  if (!argz)
 
3748
    goto cleanup;
 
3749
 
 
3750
  {
 
3751
    char *filename = 0;
 
3752
    while ((filename = argz_next (argz, argz_len, filename)))
 
3753
      if ((is_done = (*func) (filename, data2)))
 
3754
        break;
 
3755
  }
 
3756
 
 
3757
 cleanup:
 
3758
  LT_DLFREE (argz);
 
3759
 
 
3760
  return is_done;
 
3761
}
 
3762
 
 
3763
 
 
3764
/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
 
3765
   with DATA.  The filenames passed to FUNC would be suitable for
 
3766
   passing to lt_dlopenext.  The extensions are stripped so that
 
3767
   individual modules do not generate several entries (e.g. libfoo.la,
 
3768
   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
 
3769
   then the same directories that lt_dlopen would search are examined.  */
 
3770
int
 
3771
lt_dlforeachfile (search_path, func, data)
 
3772
     const char *search_path;
 
3773
     int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
 
3774
     lt_ptr data;
 
3775
{
 
3776
  int is_done = 0;
 
3777
  file_worker_func **fpptr = &func;
 
3778
 
 
3779
  if (search_path)
 
3780
    {
 
3781
      /* If a specific path was passed, search only the directories
 
3782
         listed in it.  */
 
3783
      is_done = foreach_dirinpath (search_path, 0,
 
3784
                                   foreachfile_callback, fpptr, data);
 
3785
    }
 
3786
  else
 
3787
    {
 
3788
      /* Otherwise search the default paths.  */
 
3789
      is_done = foreach_dirinpath (user_search_path, 0,
 
3790
                                   foreachfile_callback, fpptr, data);
 
3791
      if (!is_done)
 
3792
        {
 
3793
          is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
 
3794
                                       foreachfile_callback, fpptr, data);
 
3795
        }
 
3796
 
 
3797
#ifdef LTDL_SHLIBPATH_VAR
 
3798
      if (!is_done)
 
3799
        {
 
3800
          is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
 
3801
                                       foreachfile_callback, fpptr, data);
 
3802
        }
 
3803
#endif
 
3804
#ifdef LTDL_SYSSEARCHPATH
 
3805
      if (!is_done)
 
3806
        {
 
3807
          is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
 
3808
                                       foreachfile_callback, fpptr, data);
 
3809
        }
 
3810
#endif
 
3811
    }
 
3812
 
 
3813
  return is_done;
 
3814
}
 
3815
 
 
3816
int
 
3817
lt_dlclose (handle)
 
3818
     lt_dlhandle handle;
 
3819
{
 
3820
  lt_dlhandle cur, last;
 
3821
  int errors = 0;
 
3822
 
 
3823
  LT_DLMUTEX_LOCK ();
 
3824
 
 
3825
  /* check whether the handle is valid */
 
3826
  last = cur = handles;
 
3827
  while (cur && handle != cur)
 
3828
    {
 
3829
      last = cur;
 
3830
      cur = cur->next;
 
3831
    }
 
3832
 
 
3833
  if (!cur)
 
3834
    {
 
3835
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
3836
      ++errors;
 
3837
      goto done;
 
3838
    }
 
3839
 
 
3840
  handle->info.ref_count--;
 
3841
 
 
3842
  /* Note that even with resident modules, we must track the ref_count
 
3843
     correctly incase the user decides to reset the residency flag
 
3844
     later (even though the API makes no provision for that at the
 
3845
     moment).  */
 
3846
  if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
 
3847
    {
 
3848
      lt_user_data data = handle->loader->dlloader_data;
 
3849
 
 
3850
      if (handle != handles)
 
3851
        {
 
3852
          last->next = handle->next;
 
3853
        }
 
3854
      else
 
3855
        {
 
3856
          handles = handle->next;
 
3857
        }
 
3858
 
 
3859
      errors += handle->loader->module_close (data, handle->module);
 
3860
      errors += unload_deplibs(handle);
 
3861
 
 
3862
      /* It is up to the callers to free the data itself.  */
 
3863
      LT_DLFREE (handle->caller_data);
 
3864
 
 
3865
      LT_DLFREE (handle->info.filename);
 
3866
      LT_DLFREE (handle->info.name);
 
3867
      LT_DLFREE (handle);
 
3868
 
 
3869
      goto done;
 
3870
    }
 
3871
 
 
3872
  if (LT_DLIS_RESIDENT (handle))
 
3873
    {
 
3874
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
 
3875
      ++errors;
 
3876
    }
 
3877
 
 
3878
 done:
 
3879
  LT_DLMUTEX_UNLOCK ();
 
3880
 
 
3881
  return errors;
 
3882
}
 
3883
 
 
3884
lt_ptr
 
3885
lt_dlsym (handle, symbol)
 
3886
     lt_dlhandle handle;
 
3887
     const char *symbol;
 
3888
{
 
3889
  size_t lensym;
 
3890
  char  lsym[LT_SYMBOL_LENGTH];
 
3891
  char  *sym;
 
3892
  lt_ptr address;
 
3893
  lt_user_data data;
 
3894
 
 
3895
  if (!handle)
 
3896
    {
 
3897
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
3898
      return 0;
 
3899
    }
 
3900
 
 
3901
  if (!symbol)
 
3902
    {
 
3903
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
 
3904
      return 0;
 
3905
    }
 
3906
 
 
3907
  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
 
3908
                                        + LT_STRLEN (handle->info.name);
 
3909
 
 
3910
  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
 
3911
    {
 
3912
      sym = lsym;
 
3913
    }
 
3914
  else
 
3915
    {
 
3916
      sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
 
3917
      if (!sym)
 
3918
        {
 
3919
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
 
3920
          return 0;
 
3921
        }
 
3922
    }
 
3923
 
 
3924
  data = handle->loader->dlloader_data;
 
3925
  if (handle->info.name)
 
3926
    {
 
3927
      const char *saved_error;
 
3928
 
 
3929
      LT_DLMUTEX_GETERROR (saved_error);
 
3930
 
 
3931
      /* this is a libtool module */
 
3932
      if (handle->loader->sym_prefix)
 
3933
        {
 
3934
          strcpy(sym, handle->loader->sym_prefix);
 
3935
          strcat(sym, handle->info.name);
 
3936
        }
 
3937
      else
 
3938
        {
 
3939
          strcpy(sym, handle->info.name);
 
3940
        }
 
3941
 
 
3942
      strcat(sym, "_LTX_");
 
3943
      strcat(sym, symbol);
 
3944
 
 
3945
      /* try "modulename_LTX_symbol" */
 
3946
      address = handle->loader->find_sym (data, handle->module, sym);
 
3947
      if (address)
 
3948
        {
 
3949
          if (sym != lsym)
 
3950
            {
 
3951
              LT_DLFREE (sym);
 
3952
            }
 
3953
          return address;
 
3954
        }
 
3955
      LT_DLMUTEX_SETERROR (saved_error);
 
3956
    }
 
3957
 
 
3958
  /* otherwise try "symbol" */
 
3959
  if (handle->loader->sym_prefix)
 
3960
    {
 
3961
      strcpy(sym, handle->loader->sym_prefix);
 
3962
      strcat(sym, symbol);
 
3963
    }
 
3964
  else
 
3965
    {
 
3966
      strcpy(sym, symbol);
 
3967
    }
 
3968
 
 
3969
  address = handle->loader->find_sym (data, handle->module, sym);
 
3970
  if (sym != lsym)
 
3971
    {
 
3972
      LT_DLFREE (sym);
 
3973
    }
 
3974
 
 
3975
  return address;
 
3976
}
 
3977
 
 
3978
const char *
 
3979
lt_dlerror ()
 
3980
{
 
3981
  const char *error;
 
3982
 
 
3983
  LT_DLMUTEX_GETERROR (error);
 
3984
  LT_DLMUTEX_SETERROR (0);
 
3985
 
 
3986
  return error ? error : NULL;
 
3987
}
 
3988
 
 
3989
static int
 
3990
lt_dlpath_insertdir (ppath, before, dir)
 
3991
     char **ppath;
 
3992
     char *before;
 
3993
     const char *dir;
 
3994
{
 
3995
  int    errors         = 0;
 
3996
  char  *canonical      = 0;
 
3997
  char  *argz           = 0;
 
3998
  size_t argz_len       = 0;
 
3999
 
 
4000
  assert (ppath);
 
4001
  assert (dir && *dir);
 
4002
 
 
4003
  if (canonicalize_path (dir, &canonical) != 0)
 
4004
    {
 
4005
      ++errors;
 
4006
      goto cleanup;
 
4007
    }
 
4008
 
 
4009
  assert (canonical && *canonical);
 
4010
 
 
4011
  /* If *PPATH is empty, set it to DIR.  */
 
4012
  if (*ppath == 0)
 
4013
    {
 
4014
      assert (!before);         /* BEFORE cannot be set without PPATH.  */
 
4015
      assert (dir);             /* Without DIR, don't call this function!  */
 
4016
 
 
4017
      *ppath = lt_estrdup (dir);
 
4018
      if (*ppath == 0)
 
4019
        ++errors;
 
4020
 
 
4021
      return errors;
 
4022
    }
 
4023
 
 
4024
  assert (ppath && *ppath);
 
4025
 
 
4026
  if (argzize_path (*ppath, &argz, &argz_len) != 0)
 
4027
    {
 
4028
      ++errors;
 
4029
      goto cleanup;
 
4030
    }
 
4031
 
 
4032
  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
 
4033
     if *PPATH is already canonicalized, and hence does not change length
 
4034
     with respect to ARGZ.  We canonicalize each entry as it is added to
 
4035
     the search path, and don't call this function with (uncanonicalized)
 
4036
     user paths, so this is a fair assumption.  */
 
4037
  if (before)
 
4038
    {
 
4039
      assert (*ppath <= before);
 
4040
      assert (before - *ppath <= strlen (*ppath));
 
4041
 
 
4042
      before = before - *ppath + argz;
 
4043
    }
 
4044
 
 
4045
  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
 
4046
    {
 
4047
      ++errors;
 
4048
      goto cleanup;
 
4049
    }
 
4050
 
 
4051
  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
 
4052
  LT_DLMEM_REASSIGN (*ppath,  argz);
 
4053
 
 
4054
 cleanup:
 
4055
  LT_DLFREE (canonical);
 
4056
  LT_DLFREE (argz);
 
4057
 
 
4058
  return errors;
 
4059
}
 
4060
 
 
4061
int
 
4062
lt_dladdsearchdir (search_dir)
 
4063
     const char *search_dir;
 
4064
{
 
4065
  int errors = 0;
 
4066
 
 
4067
  if (search_dir && *search_dir)
 
4068
    {
 
4069
      LT_DLMUTEX_LOCK ();
 
4070
      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
 
4071
        ++errors;
 
4072
      LT_DLMUTEX_UNLOCK ();
 
4073
    }
 
4074
 
 
4075
  return errors;
 
4076
}
 
4077
 
 
4078
int
 
4079
lt_dlinsertsearchdir (before, search_dir)
 
4080
     const char *before;
 
4081
     const char *search_dir;
 
4082
{
 
4083
  int errors = 0;
 
4084
 
 
4085
  if (before)
 
4086
    {
 
4087
      LT_DLMUTEX_LOCK ();
 
4088
      if ((before < user_search_path)
 
4089
          || (before >= user_search_path + LT_STRLEN (user_search_path)))
 
4090
        {
 
4091
          LT_DLMUTEX_UNLOCK ();
 
4092
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
 
4093
          return 1;
 
4094
        }
 
4095
      LT_DLMUTEX_UNLOCK ();
 
4096
    }
 
4097
 
 
4098
  if (search_dir && *search_dir)
 
4099
    {
 
4100
      LT_DLMUTEX_LOCK ();
 
4101
      if (lt_dlpath_insertdir (&user_search_path,
 
4102
                               (char *) before, search_dir) != 0)
 
4103
        {
 
4104
          ++errors;
 
4105
        }
 
4106
      LT_DLMUTEX_UNLOCK ();
 
4107
    }
 
4108
 
 
4109
  return errors;
 
4110
}
 
4111
 
 
4112
int
 
4113
lt_dlsetsearchpath (search_path)
 
4114
     const char *search_path;
 
4115
{
 
4116
  int   errors      = 0;
 
4117
 
 
4118
  LT_DLMUTEX_LOCK ();
 
4119
  LT_DLFREE (user_search_path);
 
4120
  LT_DLMUTEX_UNLOCK ();
 
4121
 
 
4122
  if (!search_path || !LT_STRLEN (search_path))
 
4123
    {
 
4124
      return errors;
 
4125
    }
 
4126
 
 
4127
  LT_DLMUTEX_LOCK ();
 
4128
  if (canonicalize_path (search_path, &user_search_path) != 0)
 
4129
    ++errors;
 
4130
  LT_DLMUTEX_UNLOCK ();
 
4131
 
 
4132
  return errors;
 
4133
}
 
4134
 
 
4135
const char *
 
4136
lt_dlgetsearchpath ()
 
4137
{
 
4138
  const char *saved_path;
 
4139
 
 
4140
  LT_DLMUTEX_LOCK ();
 
4141
  saved_path = user_search_path;
 
4142
  LT_DLMUTEX_UNLOCK ();
 
4143
 
 
4144
  return saved_path;
 
4145
}
 
4146
 
 
4147
int
 
4148
lt_dlmakeresident (handle)
 
4149
     lt_dlhandle handle;
 
4150
{
 
4151
  int errors = 0;
 
4152
 
 
4153
  if (!handle)
 
4154
    {
 
4155
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
4156
      ++errors;
 
4157
    }
 
4158
  else
 
4159
    {
 
4160
      LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
 
4161
    }
 
4162
 
 
4163
  return errors;
 
4164
}
 
4165
 
 
4166
int
 
4167
lt_dlisresident (handle)
 
4168
     lt_dlhandle handle;
 
4169
{
 
4170
  if (!handle)
 
4171
    {
 
4172
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
4173
      return -1;
 
4174
    }
 
4175
 
 
4176
  return LT_DLIS_RESIDENT (handle);
 
4177
}
 
4178
 
 
4179
 
 
4180
 
 
4181
 
 
4182
/* --- MODULE INFORMATION --- */
 
4183
 
 
4184
const lt_dlinfo *
 
4185
lt_dlgetinfo (handle)
 
4186
     lt_dlhandle handle;
 
4187
{
 
4188
  if (!handle)
 
4189
    {
 
4190
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
 
4191
      return 0;
 
4192
    }
 
4193
 
 
4194
  return &(handle->info);
 
4195
}
 
4196
 
 
4197
lt_dlhandle
 
4198
lt_dlhandle_next (place)
 
4199
     lt_dlhandle place;
 
4200
{
 
4201
  return place ? place->next : handles;
 
4202
}
 
4203
 
 
4204
int
 
4205
lt_dlforeach (func, data)
 
4206
     int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
 
4207
     lt_ptr data;
 
4208
{
 
4209
  int errors = 0;
 
4210
  lt_dlhandle cur;
 
4211
 
 
4212
  LT_DLMUTEX_LOCK ();
 
4213
 
 
4214
  cur = handles;
 
4215
  while (cur)
 
4216
    {
 
4217
      lt_dlhandle tmp = cur;
 
4218
 
 
4219
      cur = cur->next;
 
4220
      if ((*func) (tmp, data))
 
4221
        {
 
4222
          ++errors;
 
4223
          break;
 
4224
        }
 
4225
    }
 
4226
 
 
4227
  LT_DLMUTEX_UNLOCK ();
 
4228
 
 
4229
  return errors;
 
4230
}
 
4231
 
 
4232
lt_dlcaller_id
 
4233
lt_dlcaller_register ()
 
4234
{
 
4235
  static lt_dlcaller_id last_caller_id = 0;
 
4236
  int result;
 
4237
 
 
4238
  LT_DLMUTEX_LOCK ();
 
4239
  result = ++last_caller_id;
 
4240
  LT_DLMUTEX_UNLOCK ();
 
4241
 
 
4242
  return result;
 
4243
}
 
4244
 
 
4245
lt_ptr
 
4246
lt_dlcaller_set_data (key, handle, data)
 
4247
     lt_dlcaller_id key;
 
4248
     lt_dlhandle handle;
 
4249
     lt_ptr data;
 
4250
{
 
4251
  int n_elements = 0;
 
4252
  lt_ptr stale = (lt_ptr) 0;
 
4253
  int i;
 
4254
 
 
4255
  /* This needs to be locked so that the caller data can be updated
 
4256
     simultaneously by different threads.  */
 
4257
  LT_DLMUTEX_LOCK ();
 
4258
 
 
4259
  if (handle->caller_data)
 
4260
    while (handle->caller_data[n_elements].key)
 
4261
      ++n_elements;
 
4262
 
 
4263
  for (i = 0; i < n_elements; ++i)
 
4264
    {
 
4265
      if (handle->caller_data[i].key == key)
 
4266
        {
 
4267
          stale = handle->caller_data[i].data;
 
4268
          break;
 
4269
        }
 
4270
    }
 
4271
 
 
4272
  /* Ensure that there is enough room in this handle's caller_data
 
4273
     array to accept a new element (and an empty end marker).  */
 
4274
  if (i == n_elements)
 
4275
    {
 
4276
      lt_caller_data *temp
 
4277
        = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
 
4278
 
 
4279
      if (!temp)
 
4280
        {
 
4281
          stale = 0;
 
4282
          goto done;
 
4283
        }
 
4284
 
 
4285
      handle->caller_data = temp;
 
4286
 
 
4287
      /* We only need this if we needed to allocate a new caller_data.  */
 
4288
      handle->caller_data[i].key  = key;
 
4289
      handle->caller_data[1+ i].key = 0;
 
4290
    }
 
4291
 
 
4292
  handle->caller_data[i].data = data;
 
4293
 
 
4294
 done:
 
4295
  LT_DLMUTEX_UNLOCK ();
 
4296
 
 
4297
  return stale;
 
4298
}
 
4299
 
 
4300
lt_ptr
 
4301
lt_dlcaller_get_data  (key, handle)
 
4302
     lt_dlcaller_id key;
 
4303
     lt_dlhandle handle;
 
4304
{
 
4305
  lt_ptr result = (lt_ptr) 0;
 
4306
 
 
4307
  /* This needs to be locked so that the caller data isn't updated by
 
4308
     another thread part way through this function.  */
 
4309
  LT_DLMUTEX_LOCK ();
 
4310
 
 
4311
  /* Locate the index of the element with a matching KEY.  */
 
4312
  if (handle->caller_data)
 
4313
    {
 
4314
      int i;
 
4315
      for (i = 0; handle->caller_data[i].key; ++i)
 
4316
        {
 
4317
          if (handle->caller_data[i].key == key)
 
4318
            {
 
4319
              result = handle->caller_data[i].data;
 
4320
              break;
 
4321
            }
 
4322
        }
 
4323
    }
 
4324
 
 
4325
  LT_DLMUTEX_UNLOCK ();
 
4326
 
 
4327
  return result;
 
4328
}
 
4329
 
 
4330
 
 
4331
 
 
4332
/* --- USER MODULE LOADER API --- */
 
4333
 
 
4334
 
 
4335
int
 
4336
lt_dlloader_add (place, dlloader, loader_name)
 
4337
     lt_dlloader *place;
 
4338
     const struct lt_user_dlloader *dlloader;
 
4339
     const char *loader_name;
 
4340
{
 
4341
  int errors = 0;
 
4342
  lt_dlloader *node = 0, *ptr = 0;
 
4343
 
 
4344
  if ((dlloader == 0)   /* diagnose null parameters */
 
4345
      || (dlloader->module_open == 0)
 
4346
      || (dlloader->module_close == 0)
 
4347
      || (dlloader->find_sym == 0))
 
4348
    {
 
4349
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
 
4350
      return 1;
 
4351
    }
 
4352
 
 
4353
  /* Create a new dlloader node with copies of the user callbacks.  */
 
4354
  node = LT_EMALLOC (lt_dlloader, 1);
 
4355
  if (!node)
 
4356
    return 1;
 
4357
 
 
4358
  node->next            = 0;
 
4359
  node->loader_name     = loader_name;
 
4360
  node->sym_prefix      = dlloader->sym_prefix;
 
4361
  node->dlloader_exit   = dlloader->dlloader_exit;
 
4362
  node->module_open     = dlloader->module_open;
 
4363
  node->module_close    = dlloader->module_close;
 
4364
  node->find_sym        = dlloader->find_sym;
 
4365
  node->dlloader_data   = dlloader->dlloader_data;
 
4366
 
 
4367
  LT_DLMUTEX_LOCK ();
 
4368
  if (!loaders)
 
4369
    {
 
4370
      /* If there are no loaders, NODE becomes the list! */
 
4371
      loaders = node;
 
4372
    }
 
4373
  else if (!place)
 
4374
    {
 
4375
      /* If PLACE is not set, add NODE to the end of the
 
4376
         LOADERS list. */
 
4377
      for (ptr = loaders; ptr->next; ptr = ptr->next)
 
4378
        {
 
4379
          /*NOWORK*/;
 
4380
        }
 
4381
 
 
4382
      ptr->next = node;
 
4383
    }
 
4384
  else if (loaders == place)
 
4385
    {
 
4386
      /* If PLACE is the first loader, NODE goes first. */
 
4387
      node->next = place;
 
4388
      loaders = node;
 
4389
    }
 
4390
  else
 
4391
    {
 
4392
      /* Find the node immediately preceding PLACE. */
 
4393
      for (ptr = loaders; ptr->next != place; ptr = ptr->next)
 
4394
        {
 
4395
          /*NOWORK*/;
 
4396
        }
 
4397
 
 
4398
      if (ptr->next != place)
 
4399
        {
 
4400
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
 
4401
          ++errors;
 
4402
        }
 
4403
      else
 
4404
        {
 
4405
          /* Insert NODE between PTR and PLACE. */
 
4406
          node->next = place;
 
4407
          ptr->next  = node;
 
4408
        }
 
4409
    }
 
4410
 
 
4411
  LT_DLMUTEX_UNLOCK ();
 
4412
 
 
4413
  return errors;
 
4414
}
 
4415
 
 
4416
int
 
4417
lt_dlloader_remove (loader_name)
 
4418
     const char *loader_name;
 
4419
{
 
4420
  lt_dlloader *place = lt_dlloader_find (loader_name);
 
4421
  lt_dlhandle handle;
 
4422
  int errors = 0;
 
4423
 
 
4424
  if (!place)
 
4425
    {
 
4426
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
 
4427
      return 1;
 
4428
    }
 
4429
 
 
4430
  LT_DLMUTEX_LOCK ();
 
4431
 
 
4432
  /* Fail if there are any open modules which use this loader. */
 
4433
  for  (handle = handles; handle; handle = handle->next)
 
4434
    {
 
4435
      if (handle->loader == place)
 
4436
        {
 
4437
          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
 
4438
          ++errors;
 
4439
          goto done;
 
4440
        }
 
4441
    }
 
4442
 
 
4443
  if (place == loaders)
 
4444
    {
 
4445
      /* PLACE is the first loader in the list. */
 
4446
      loaders = loaders->next;
 
4447
    }
 
4448
  else
 
4449
    {
 
4450
      /* Find the loader before the one being removed. */
 
4451
      lt_dlloader *prev;
 
4452
      for (prev = loaders; prev->next; prev = prev->next)
 
4453
        {
 
4454
          if (!strcmp (prev->next->loader_name, loader_name))
 
4455
            {
 
4456
              break;
 
4457
            }
 
4458
        }
 
4459
 
 
4460
      place = prev->next;
 
4461
      prev->next = prev->next->next;
 
4462
    }
 
4463
 
 
4464
  if (place->dlloader_exit)
 
4465
    {
 
4466
      errors = place->dlloader_exit (place->dlloader_data);
 
4467
    }
 
4468
 
 
4469
  LT_DLFREE (place);
 
4470
 
 
4471
 done:
 
4472
  LT_DLMUTEX_UNLOCK ();
 
4473
 
 
4474
  return errors;
 
4475
}
 
4476
 
 
4477
lt_dlloader *
 
4478
lt_dlloader_next (place)
 
4479
     lt_dlloader *place;
 
4480
{
 
4481
  lt_dlloader *next;
 
4482
 
 
4483
  LT_DLMUTEX_LOCK ();
 
4484
  next = place ? place->next : loaders;
 
4485
  LT_DLMUTEX_UNLOCK ();
 
4486
 
 
4487
  return next;
 
4488
}
 
4489
 
 
4490
const char *
 
4491
lt_dlloader_name (place)
 
4492
     lt_dlloader *place;
 
4493
{
 
4494
  const char *name = 0;
 
4495
 
 
4496
  if (place)
 
4497
    {
 
4498
      LT_DLMUTEX_LOCK ();
 
4499
      name = place ? place->loader_name : 0;
 
4500
      LT_DLMUTEX_UNLOCK ();
 
4501
    }
 
4502
  else
 
4503
    {
 
4504
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
 
4505
    }
 
4506
 
 
4507
  return name;
 
4508
}
 
4509
 
 
4510
lt_user_data *
 
4511
lt_dlloader_data (place)
 
4512
     lt_dlloader *place;
 
4513
{
 
4514
  lt_user_data *data = 0;
 
4515
 
 
4516
  if (place)
 
4517
    {
 
4518
      LT_DLMUTEX_LOCK ();
 
4519
      data = place ? &(place->dlloader_data) : 0;
 
4520
      LT_DLMUTEX_UNLOCK ();
 
4521
    }
 
4522
  else
 
4523
    {
 
4524
      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
 
4525
    }
 
4526
 
 
4527
  return data;
 
4528
}
 
4529
 
 
4530
lt_dlloader *
 
4531
lt_dlloader_find (loader_name)
 
4532
     const char *loader_name;
 
4533
{
 
4534
  lt_dlloader *place = 0;
 
4535
 
 
4536
  LT_DLMUTEX_LOCK ();
 
4537
  for (place = loaders; place; place = place->next)
 
4538
    {
 
4539
      if (strcmp (place->loader_name, loader_name) == 0)
 
4540
        {
 
4541
          break;
 
4542
        }
 
4543
    }
 
4544
  LT_DLMUTEX_UNLOCK ();
 
4545
 
 
4546
  return place;
 
4547
}