~diwic/ubuntu/lucid/pulseaudio/bugfixes

« back to all changes in this revision

Viewing changes to libltdl/ltdl.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2006-11-12 20:00:18 UTC
  • Revision ID: james.westby@ubuntu.com-20061112200018-oji9njq7rr3te53k
Tags: upstream-0.9.5
ImportĀ upstreamĀ versionĀ 0.9.5

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