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