~ubuntu-branches/ubuntu/wily/scim/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/32_scim-1.4.8-fix-dlopen.patch/src/ltdl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Rolf Leggewie
  • Date: 2010-08-11 18:28:44 UTC
  • mfrom: (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100811182844-rnn95k63cwehtm75
Tags: 1.4.9-5
* debian/copyright: add my copyright
* debian/control: update to standard 3.9.1, no further changes necessary

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