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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [libltdl/] [ltdl.c] - Blame information for rev 830

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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