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