OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [libltdl/] [ltdl.c] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.