00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #if HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #if HAVE_UNISTD_H
00033 # include <unistd.h>
00034 #endif
00035
00036 #if HAVE_STDIO_H
00037 # include <stdio.h>
00038 #endif
00039
00040 #if HAVE_STDLIB_H
00041 # include <stdlib.h>
00042 #endif
00043
00044 #if HAVE_STRING_H
00045 # include <string.h>
00046 #else
00047 # if HAVE_STRINGS_H
00048 # include <strings.h>
00049 # endif
00050 #endif
00051
00052 #if HAVE_CTYPE_H
00053 # include <ctype.h>
00054 #endif
00055
00056 #if HAVE_MALLOC_H
00057 # include <malloc.h>
00058 #endif
00059
00060 #if HAVE_MEMORY_H
00061 # include <memory.h>
00062 #endif
00063
00064 #if HAVE_ERRNO_H
00065 # include <errno.h>
00066 #endif
00067
00068 #if HAVE_DIRENT_H
00069 # include <dirent.h>
00070 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
00071 #else
00072 # define dirent direct
00073 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
00074 # if HAVE_SYS_NDIR_H
00075 # include <sys/ndir.h>
00076 # endif
00077 # if HAVE_SYS_DIR_H
00078 # include <sys/dir.h>
00079 # endif
00080 # if HAVE_NDIR_H
00081 # include <ndir.h>
00082 # endif
00083 #endif
00084
00085 #if HAVE_ARGZ_H
00086 # include <argz.h>
00087 #endif
00088
00089 #if HAVE_ASSERT_H
00090 # include <assert.h>
00091 #else
00092 # define assert(arg) ((void) 0)
00093 #endif
00094
00095 #include "ltdl.h"
00096
00097
00098
00099
00100
00101
00102
00103 #ifdef DLL_EXPORT
00104 # define LT_GLOBAL_DATA __declspec(dllexport)
00105 #else
00106 # define LT_GLOBAL_DATA
00107 #endif
00108
00109
00110 #undef LT_READTEXT_MODE
00111 #ifdef __WINDOWS__
00112 # define LT_READTEXT_MODE "rt"
00113 #else
00114 # define LT_READTEXT_MODE "r"
00115 #endif
00116
00117
00118
00119
00120
00121
00122
00123
00124 #undef LTDL_SEARCHPATH_VAR
00125 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
00126
00127
00128 #undef LTDL_ARCHIVE_EXT
00129 #define LTDL_ARCHIVE_EXT ".la"
00130
00131
00132 #ifndef LT_FILENAME_MAX
00133 # define LT_FILENAME_MAX 1024
00134 #endif
00135
00136
00137 #undef LT_SYMBOL_LENGTH
00138 #define LT_SYMBOL_LENGTH 128
00139
00140
00141 #undef LT_SYMBOL_OVERHEAD
00142 #define LT_SYMBOL_OVERHEAD 5
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 static char *lt_estrdup LT_PARAMS((const char *str));
00154 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
00155 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
00156
00157 static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size));
00158
00159
00160 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
00161 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
00162 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
00163 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
00164 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
00165 = (void (*) LT_PARAMS((lt_ptr))) free;
00166
00167
00168
00169 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
00170 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
00171 #define LT_DLFREE(p) \
00172 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
00173
00174 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
00175 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
00176
00177 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
00178 if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; } \
00179 } LT_STMT_END
00180
00181
00182
00183
00184
00185 #undef strdup
00186 #define strdup rpl_strdup
00187
00188 static char *strdup LT_PARAMS((const char *str));
00189
00190 char *
00191 strdup(str)
00192 const char *str;
00193 {
00194 char *tmp = 0;
00195
00196 if (str)
00197 {
00198 tmp = LT_DLMALLOC (char, 1+ strlen (str));
00199 if (tmp)
00200 {
00201 strcpy(tmp, str);
00202 }
00203 }
00204
00205 return tmp;
00206 }
00207
00208
00209 #if ! HAVE_STRCMP
00210
00211 #undef strcmp
00212 #define strcmp rpl_strcmp
00213
00214 static int strcmp LT_PARAMS((const char *str1, const char *str2));
00215
00216 int
00217 strcmp (str1, str2)
00218 const char *str1;
00219 const char *str2;
00220 {
00221 if (str1 == str2)
00222 return 0;
00223 if (str1 == 0)
00224 return -1;
00225 if (str2 == 0)
00226 return 1;
00227
00228 for (;*str1 && *str2; ++str1, ++str2)
00229 {
00230 if (*str1 != *str2)
00231 break;
00232 }
00233
00234 return (int)(*str1 - *str2);
00235 }
00236 #endif
00237
00238
00239 #if ! HAVE_STRCHR
00240
00241 # if HAVE_INDEX
00242 # define strchr index
00243 # else
00244 # define strchr rpl_strchr
00245
00246 static const char *strchr LT_PARAMS((const char *str, int ch));
00247
00248 const char*
00249 strchr(str, ch)
00250 const char *str;
00251 int ch;
00252 {
00253 const char *p;
00254
00255 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
00256 ;
00257
00258 return (*p == (char)ch) ? p : 0;
00259 }
00260
00261 # endif
00262 #endif
00263
00264
00265 #if ! HAVE_STRRCHR
00266
00267 # if HAVE_RINDEX
00268 # define strrchr rindex
00269 # else
00270 # define strrchr rpl_strrchr
00271
00272 static const char *strrchr LT_PARAMS((const char *str, int ch));
00273
00274 const char*
00275 strrchr(str, ch)
00276 const char *str;
00277 int ch;
00278 {
00279 const char *p, *q = 0;
00280
00281 for (p = str; *p != LT_EOS_CHAR; ++p)
00282 {
00283 if (*p == (char) ch)
00284 {
00285 q = p;
00286 }
00287 }
00288
00289 return q;
00290 }
00291
00292 # endif
00293 #endif
00294
00295
00296
00297
00298
00299 #if ! HAVE_MEMCPY
00300
00301 # if HAVE_BCOPY
00302 # define memcpy(dest, src, size) bcopy (src, dest, size)
00303 # else
00304 # define memcpy rpl_memcpy
00305
00306 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00307
00308 lt_ptr
00309 memcpy (dest, src, size)
00310 lt_ptr dest;
00311 const lt_ptr src;
00312 size_t size;
00313 {
00314 size_t i = 0;
00315
00316 for (i = 0; i < size; ++i)
00317 {
00318 dest[i] = src[i];
00319 }
00320
00321 return dest;
00322 }
00323
00324 # endif
00325 #endif
00326
00327 #if ! HAVE_MEMMOVE
00328 # define memmove rpl_memmove
00329
00330 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00331
00332 lt_ptr
00333 memmove (dest, src, size)
00334 lt_ptr dest;
00335 const lt_ptr src;
00336 size_t size;
00337 {
00338 size_t i;
00339
00340 if (dest < src)
00341 for (i = 0; i < size; ++i)
00342 {
00343 dest[i] = src[i];
00344 }
00345 else if (dest > src)
00346 for (i = size -1; i >= 0; --i)
00347 {
00348 dest[i] = src[i];
00349 }
00350
00351 return dest;
00352 }
00353
00354 #endif
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 #undef realloc
00365 #define realloc rpl_realloc
00366
00367 lt_ptr
00368 realloc (ptr, size)
00369 lt_ptr ptr;
00370 size_t size;
00371 {
00372 if (size <= 0)
00373 {
00374
00375 if (ptr != 0)
00376 {
00377 lt_dlfree (ptr);
00378 }
00379
00380 return (lt_ptr) 0;
00381 }
00382 else if (ptr == 0)
00383 {
00384
00385 return lt_dlmalloc (size);
00386 }
00387 else
00388 {
00389
00390 lt_ptr mem = lt_dlmalloc (size);
00391
00392 if (mem)
00393 {
00394 memcpy (mem, ptr, size);
00395 lt_dlfree (ptr);
00396 }
00397
00398
00399
00400 return mem;
00401 }
00402 }
00403
00404
00405 #if ! HAVE_ARGZ_APPEND
00406 # define argz_append rpl_argz_append
00407
00408 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
00409 const char *buf, size_t buf_len));
00410
00411 error_t
00412 argz_append (pargz, pargz_len, buf, buf_len)
00413 char **pargz;
00414 size_t *pargz_len;
00415 const char *buf;
00416 size_t buf_len;
00417 {
00418 size_t argz_len;
00419 char *argz;
00420
00421 assert (pargz);
00422 assert (pargz_len);
00423 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
00424
00425
00426 if (buf_len == 0)
00427 return 0;
00428
00429
00430 argz_len = *pargz_len + buf_len;
00431 argz = LT_DLREALLOC (char, *pargz, argz_len);
00432 if (!argz)
00433 return ENOMEM;
00434
00435
00436 memcpy (argz + *pargz_len, buf, buf_len);
00437
00438
00439 *pargz = argz;
00440 *pargz_len = argz_len;
00441
00442 return 0;
00443 }
00444 #endif
00445
00446
00447 #if ! HAVE_ARGZ_CREATE_SEP
00448 # define argz_create_sep rpl_argz_create_sep
00449
00450 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
00451 char **pargz, size_t *pargz_len));
00452
00453 error_t
00454 argz_create_sep (str, delim, pargz, pargz_len)
00455 const char *str;
00456 int delim;
00457 char **pargz;
00458 size_t *pargz_len;
00459 {
00460 size_t argz_len;
00461 char *argz = 0;
00462
00463 assert (str);
00464 assert (pargz);
00465 assert (pargz_len);
00466
00467
00468
00469 argz_len = 1+ LT_STRLEN (str);
00470 if (argz_len)
00471 {
00472 const char *p;
00473 char *q;
00474
00475 argz = LT_DLMALLOC (char, argz_len);
00476 if (!argz)
00477 return ENOMEM;
00478
00479 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
00480 {
00481 if (*p == delim)
00482 {
00483
00484
00485 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
00486 *q++ = LT_EOS_CHAR;
00487 else
00488 --argz_len;
00489 }
00490 else
00491 *q++ = *p;
00492 }
00493
00494 *q = *p;
00495 }
00496
00497
00498 if (!argz_len)
00499 LT_DLFREE (argz);
00500
00501
00502 *pargz = argz;
00503 *pargz_len = argz_len;
00504
00505 return 0;
00506 }
00507 #endif
00508
00509
00510 #if ! HAVE_ARGZ_INSERT
00511 # define argz_insert rpl_argz_insert
00512
00513 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
00514 char *before, const char *entry));
00515
00516 error_t
00517 argz_insert (pargz, pargz_len, before, entry)
00518 char **pargz;
00519 size_t *pargz_len;
00520 char *before;
00521 const char *entry;
00522 {
00523 assert (pargz);
00524 assert (pargz_len);
00525 assert (entry && *entry);
00526
00527
00528
00529 assert ((!*pargz && !*pargz_len && !before)
00530 || ((*pargz <= before) && (before < (*pargz + *pargz_len))));
00531
00532
00533
00534 if (!before)
00535 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
00536
00537
00538
00539
00540 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
00541 --before;
00542
00543 {
00544 size_t entry_len = 1+ LT_STRLEN (entry);
00545 size_t argz_len = *pargz_len + entry_len;
00546 size_t offset = before - *pargz;
00547 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
00548
00549 if (!argz)
00550 return ENOMEM;
00551
00552
00553
00554 before = argz + offset;
00555
00556
00557
00558
00559 memmove (before + entry_len, before, *pargz_len - offset);
00560 memcpy (before, entry, entry_len);
00561
00562
00563 *pargz = argz;
00564 *pargz_len = argz_len;
00565 }
00566
00567 return 0;
00568 }
00569 #endif
00570
00571
00572 #if ! HAVE_ARGZ_NEXT
00573 # define argz_next rpl_argz_next
00574
00575 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
00576 const char *entry));
00577
00578 char *
00579 argz_next (argz, argz_len, entry)
00580 char *argz;
00581 size_t argz_len;
00582 const char *entry;
00583 {
00584 assert ((argz && argz_len) || (!argz && !argz_len));
00585
00586 if (entry)
00587 {
00588
00589
00590 assert ((!argz && !argz_len)
00591 || ((argz <= entry) && (entry < (argz + argz_len))));
00592
00593
00594
00595 entry = 1+ strchr (entry, LT_EOS_CHAR);
00596
00597
00598
00599 return (entry >= argz + argz_len) ? 0 : (char *) entry;
00600 }
00601 else
00602 {
00603
00604
00605
00606
00607 if (argz_len > 0)
00608 return argz;
00609 else
00610 return 0;
00611 }
00612 }
00613 #endif
00614
00615
00616
00617 #if ! HAVE_ARGZ_STRINGIFY
00618 # define argz_stringify rpl_argz_stringify
00619
00620 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
00621 int sep));
00622
00623 void
00624 argz_stringify (argz, argz_len, sep)
00625 char *argz;
00626 size_t argz_len;
00627 int sep;
00628 {
00629 assert ((argz && argz_len) || (!argz && !argz_len));
00630
00631 if (sep)
00632 {
00633 --argz_len;
00634 while (--argz_len > 0)
00635 {
00636 if (argz[argz_len] == LT_EOS_CHAR)
00637 argz[argz_len] = sep;
00638 }
00639 }
00640 }
00641 #endif
00642
00643
00644
00645
00646
00647
00648
00649
00650 typedef struct {
00651 lt_dlcaller_id key;
00652 lt_ptr data;
00653 } lt_caller_data;
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 static const char *lt_dlerror_strings[] =
00665 {
00666 #define LT_ERROR(name, diagnostic) (diagnostic),
00667 lt_dlerror_table
00668 #undef LT_ERROR
00669
00670 0
00671 };
00672
00673
00674 struct lt_dlloader {
00675 struct lt_dlloader *next;
00676 const char *loader_name;
00677 const char *sym_prefix;
00678 lt_module_open *module_open;
00679 lt_module_close *module_close;
00680 lt_find_sym *find_sym;
00681 lt_dlloader_exit *dlloader_exit;
00682 lt_user_data dlloader_data;
00683 };
00684
00685 struct lt_dlhandle_struct {
00686 struct lt_dlhandle_struct *next;
00687 lt_dlloader *loader;
00688 lt_dlinfo info;
00689 int depcount;
00690 lt_dlhandle *deplibs;
00691 lt_module module;
00692 lt_ptr system;
00693 lt_caller_data *caller_data;
00694 int flags;
00695 };
00696
00697
00698
00699 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
00700 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
00701
00702 #define LT_DLRESIDENT_FLAG (0x01 << 0)
00703
00704
00705 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
00706
00707
00708 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
00709
00710 static const char objdir[] = LTDL_OBJDIR;
00711 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
00712 #ifdef LTDL_SHLIB_EXT
00713 static const char shlib_ext[] = LTDL_SHLIB_EXT;
00714 #endif
00715 #ifdef LTDL_SYSSEARCHPATH
00716 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
00717 #endif
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
00731 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
00732 } LT_STMT_END
00733 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
00734 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
00735 } LT_STMT_END
00736 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
00737 if (lt_dlmutex_seterror_func) \
00738 (*lt_dlmutex_seterror_func) (errormsg); \
00739 else lt_dllast_error = (errormsg); } LT_STMT_END
00740 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
00741 if (lt_dlmutex_seterror_func) \
00742 (errormsg) = (*lt_dlmutex_geterror_func) (); \
00743 else (errormsg) = lt_dllast_error; } LT_STMT_END
00744
00745
00746
00747 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
00748 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
00749 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
00750 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
00751 static const char *lt_dllast_error = 0;
00752
00753
00754
00755
00756
00757
00758 int
00759 lt_dlmutex_register (lock, unlock, seterror, geterror)
00760 lt_dlmutex_lock *lock;
00761 lt_dlmutex_unlock *unlock;
00762 lt_dlmutex_seterror *seterror;
00763 lt_dlmutex_geterror *geterror;
00764 {
00765 lt_dlmutex_unlock *old_unlock = unlock;
00766 int errors = 0;
00767
00768
00769 LT_DLMUTEX_LOCK ();
00770
00771 if ((lock && unlock && seterror && geterror)
00772 || !(lock || unlock || seterror || geterror))
00773 {
00774 lt_dlmutex_lock_func = lock;
00775 lt_dlmutex_unlock_func = unlock;
00776 lt_dlmutex_geterror_func = geterror;
00777 }
00778 else
00779 {
00780 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
00781 ++errors;
00782 }
00783
00784
00785
00786 if (old_unlock)
00787 (*old_unlock) ();
00788
00789
00790
00791 return errors;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800 static const char **user_error_strings = 0;
00801 static int errorcount = LT_ERROR_MAX;
00802
00803 int
00804 lt_dladderror (diagnostic)
00805 const char *diagnostic;
00806 {
00807 int errindex = 0;
00808 int result = -1;
00809 const char **temp = (const char **) 0;
00810
00811 assert (diagnostic);
00812
00813 LT_DLMUTEX_LOCK ();
00814
00815 errindex = errorcount - LT_ERROR_MAX;
00816 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
00817 if (temp)
00818 {
00819 user_error_strings = temp;
00820 user_error_strings[errindex] = diagnostic;
00821 result = errorcount++;
00822 }
00823
00824 LT_DLMUTEX_UNLOCK ();
00825
00826 return result;
00827 }
00828
00829 int
00830 lt_dlseterror (errindex)
00831 int errindex;
00832 {
00833 int errors = 0;
00834
00835 LT_DLMUTEX_LOCK ();
00836
00837 if (errindex >= errorcount || errindex < 0)
00838 {
00839
00840 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
00841 ++errors;
00842 }
00843 else if (errindex < LT_ERROR_MAX)
00844 {
00845
00846 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
00847 }
00848 else
00849 {
00850
00851 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
00852 }
00853
00854 LT_DLMUTEX_UNLOCK ();
00855
00856 return errors;
00857 }
00858
00859 lt_ptr
00860 lt_emalloc (size)
00861 size_t size;
00862 {
00863 lt_ptr mem = lt_dlmalloc (size);
00864 if (size && !mem)
00865 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
00866 return mem;
00867 }
00868
00869 lt_ptr
00870 lt_erealloc (addr, size)
00871 lt_ptr addr;
00872 size_t size;
00873 {
00874 lt_ptr mem = realloc (addr, size);
00875 if (size && !mem)
00876 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
00877 return mem;
00878 }
00879
00880 char *
00881 lt_estrdup (str)
00882 const char *str;
00883 {
00884 char *dup = strdup (str);
00885 if (LT_STRLEN (str) && !dup)
00886 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
00887 return dup;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 #if HAVE_LIBDL && !defined(__CYGWIN__)
00901
00902
00903
00904 #if HAVE_DLFCN_H
00905 # include <dlfcn.h>
00906 #endif
00907
00908 #if HAVE_SYS_DL_H
00909 # include <sys/dl.h>
00910 #endif
00911
00912 #ifdef RTLD_GLOBAL
00913 # define LT_GLOBAL RTLD_GLOBAL
00914 #else
00915 # ifdef DL_GLOBAL
00916 # define LT_GLOBAL DL_GLOBAL
00917 # endif
00918 #endif
00919 #ifndef LT_GLOBAL
00920 # define LT_GLOBAL 0
00921 #endif
00922
00923
00924
00925 #ifndef LT_LAZY_OR_NOW
00926 # ifdef RTLD_LAZY
00927 # define LT_LAZY_OR_NOW RTLD_LAZY
00928 # else
00929 # ifdef DL_LAZY
00930 # define LT_LAZY_OR_NOW DL_LAZY
00931 # endif
00932 # endif
00933 #endif
00934 #ifndef LT_LAZY_OR_NOW
00935 # ifdef RTLD_NOW
00936 # define LT_LAZY_OR_NOW RTLD_NOW
00937 # else
00938 # ifdef DL_NOW
00939 # define LT_LAZY_OR_NOW DL_NOW
00940 # endif
00941 # endif
00942 #endif
00943 #ifndef LT_LAZY_OR_NOW
00944 # define LT_LAZY_OR_NOW 0
00945 #endif
00946
00947 #if HAVE_DLERROR
00948 # define DLERROR(arg) dlerror ()
00949 #else
00950 # define DLERROR(arg) LT_DLSTRERROR (arg)
00951 #endif
00952
00953 static lt_module
00954 sys_dl_open (loader_data, filename)
00955 lt_user_data loader_data;
00956 const char *filename;
00957 {
00958 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
00959
00960 if (!module)
00961 {
00962 const char* tmp = dlerror();
00963 const char* match = strstr (tmp, "undefined symbol:" );
00964 if ( match )
00965 {
00966 fprintf (stderr, "Failed to open shared lib: %s\n"
00967 " Error: %s\n",
00968 filename, tmp);
00969 }
00970 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
00971 }
00972
00973 return module;
00974 }
00975
00976 static int
00977 sys_dl_close (loader_data, module)
00978 lt_user_data loader_data;
00979 lt_module module;
00980 {
00981 int errors = 0;
00982
00983 if (dlclose (module) != 0)
00984 {
00985 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
00986 ++errors;
00987 }
00988
00989 return errors;
00990 }
00991
00992 static lt_ptr
00993 sys_dl_sym (loader_data, module, symbol)
00994 lt_user_data loader_data;
00995 lt_module module;
00996 const char *symbol;
00997 {
00998 lt_ptr address = dlsym (module, symbol);
00999
01000 if (!address)
01001 {
01002 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
01003 }
01004
01005 return address;
01006 }
01007
01008 static struct lt_user_dlloader sys_dl =
01009 {
01010 # ifdef NEED_USCORE
01011 "_",
01012 # else
01013 0,
01014 # endif
01015 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
01016
01017
01018 #endif
01019
01020
01021
01022
01023
01024 #if HAVE_SHL_LOAD
01025
01026
01027
01028 #ifdef HAVE_DL_H
01029 # include <dl.h>
01030 #endif
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 #ifndef DYNAMIC_PATH
01064 # define DYNAMIC_PATH 0
01065 #endif
01066 #ifndef BIND_RESTRICTED
01067 # define BIND_RESTRICTED 0
01068 #endif
01069
01070 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
01071
01072 static lt_module
01073 sys_shl_open (loader_data, filename)
01074 lt_user_data loader_data;
01075 const char *filename;
01076 {
01077 static shl_t self = (shl_t) 0;
01078 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
01079
01080
01081
01082
01083
01084 if (!self)
01085 {
01086 lt_ptr address;
01087 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
01088 }
01089
01090 if (!filename)
01091 {
01092 module = self;
01093 }
01094 else
01095 {
01096 module = shl_load (filename, LT_BIND_FLAGS, 0L);
01097
01098 if (!module)
01099 {
01100 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01101 }
01102 }
01103
01104 return module;
01105 }
01106
01107 static int
01108 sys_shl_close (loader_data, module)
01109 lt_user_data loader_data;
01110 lt_module module;
01111 {
01112 int errors = 0;
01113
01114 if (module && (shl_unload ((shl_t) (module)) != 0))
01115 {
01116 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01117 ++errors;
01118 }
01119
01120 return errors;
01121 }
01122
01123 static lt_ptr
01124 sys_shl_sym (loader_data, module, symbol)
01125 lt_user_data loader_data;
01126 lt_module module;
01127 const char *symbol;
01128 {
01129 lt_ptr address = 0;
01130
01131
01132 if (module == (lt_module) 0)
01133 {
01134 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
01135 }
01136 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
01137 {
01138 if (!address)
01139 {
01140 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01141 }
01142 }
01143
01144 return address;
01145 }
01146
01147 static struct lt_user_dlloader sys_shl = {
01148 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
01149 };
01150
01151 #endif
01152
01153
01154
01155
01156
01157
01158 #ifdef __WINDOWS__
01159
01160
01161
01162 #include <windows.h>
01163
01164
01165 static lt_dlhandle handles;
01166
01167 static lt_module
01168 sys_wll_open (loader_data, filename)
01169 lt_user_data loader_data;
01170 const char *filename;
01171 {
01172 lt_dlhandle cur;
01173 lt_module module = 0;
01174 const char *errormsg = 0;
01175 char *searchname = 0;
01176 char *ext;
01177 char self_name_buf[MAX_PATH];
01178
01179 if (!filename)
01180 {
01181
01182 *self_name_buf = 0;
01183 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
01184 filename = ext = self_name_buf;
01185 }
01186 else
01187 {
01188 ext = strrchr (filename, '.');
01189 }
01190
01191 if (ext)
01192 {
01193
01194 searchname = lt_estrdup (filename);
01195 }
01196 else
01197 {
01198
01199
01200 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
01201 if (searchname)
01202 sprintf (searchname, "%s.", filename);
01203 }
01204 if (!searchname)
01205 return 0;
01206
01207 #if __CYGWIN__
01208 {
01209 char wpath[MAX_PATH];
01210 cygwin_conv_to_full_win32_path(searchname, wpath);
01211 module = LoadLibrary(wpath);
01212 }
01213 #else
01214 module = LoadLibrary (searchname);
01215 #endif
01216 LT_DLFREE (searchname);
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 LT_DLMUTEX_LOCK ();
01227 cur = handles;
01228 while (cur)
01229 {
01230 if (!cur->module)
01231 {
01232 cur = 0;
01233 break;
01234 }
01235
01236 if (cur->module == module)
01237 {
01238 break;
01239 }
01240
01241 cur = cur->next;
01242 }
01243 LT_DLMUTEX_UNLOCK ();
01244
01245 if (cur || !module)
01246 {
01247 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01248 module = 0;
01249 }
01250
01251 return module;
01252 }
01253
01254 static int
01255 sys_wll_close (loader_data, module)
01256 lt_user_data loader_data;
01257 lt_module module;
01258 {
01259 int errors = 0;
01260
01261 if (FreeLibrary(module) == 0)
01262 {
01263 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01264 ++errors;
01265 }
01266
01267 return errors;
01268 }
01269
01270 static lt_ptr
01271 sys_wll_sym (loader_data, module, symbol)
01272 lt_user_data loader_data;
01273 lt_module module;
01274 const char *symbol;
01275 {
01276 lt_ptr address = GetProcAddress (module, symbol);
01277
01278 if (!address)
01279 {
01280 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01281 }
01282
01283 return address;
01284 }
01285
01286 static struct lt_user_dlloader sys_wll = {
01287 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
01288 };
01289
01290 #endif
01291
01292
01293
01294
01295
01296
01297
01298 #ifdef __BEOS__
01299
01300
01301
01302 #include <kernel/image.h>
01303
01304 static lt_module
01305 sys_bedl_open (loader_data, filename)
01306 lt_user_data loader_data;
01307 const char *filename;
01308 {
01309 image_id image = 0;
01310
01311 if (filename)
01312 {
01313 image = load_add_on (filename);
01314 }
01315 else
01316 {
01317 image_info info;
01318 int32 cookie = 0;
01319 if (get_next_image_info (0, &cookie, &info) == B_OK)
01320 image = load_add_on (info.name);
01321 }
01322
01323 if (image <= 0)
01324 {
01325 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01326 image = 0;
01327 }
01328
01329 return (lt_module) image;
01330 }
01331
01332 static int
01333 sys_bedl_close (loader_data, module)
01334 lt_user_data loader_data;
01335 lt_module module;
01336 {
01337 int errors = 0;
01338
01339 if (unload_add_on ((image_id) module) != B_OK)
01340 {
01341 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01342 ++errors;
01343 }
01344
01345 return errors;
01346 }
01347
01348 static lt_ptr
01349 sys_bedl_sym (loader_data, module, symbol)
01350 lt_user_data loader_data;
01351 lt_module module;
01352 const char *symbol;
01353 {
01354 lt_ptr address = 0;
01355 image_id image = (image_id) module;
01356
01357 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
01358 {
01359 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01360 address = 0;
01361 }
01362
01363 return address;
01364 }
01365
01366 static struct lt_user_dlloader sys_bedl = {
01367 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
01368 };
01369
01370 #endif
01371
01372
01373
01374
01375
01376
01377
01378 #if HAVE_DLD
01379
01380
01381
01382 #if HAVE_DLD_H
01383 #include <dld.h>
01384 #endif
01385
01386 static lt_module
01387 sys_dld_open (loader_data, filename)
01388 lt_user_data loader_data;
01389 const char *filename;
01390 {
01391 lt_module module = strdup (filename);
01392
01393 if (dld_link (filename) != 0)
01394 {
01395 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01396 LT_DLFREE (module);
01397 module = 0;
01398 }
01399
01400 return module;
01401 }
01402
01403 static int
01404 sys_dld_close (loader_data, module)
01405 lt_user_data loader_data;
01406 lt_module module;
01407 {
01408 int errors = 0;
01409
01410 if (dld_unlink_by_file ((char*)(module), 1) != 0)
01411 {
01412 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01413 ++errors;
01414 }
01415 else
01416 {
01417 LT_DLFREE (module);
01418 }
01419
01420 return errors;
01421 }
01422
01423 static lt_ptr
01424 sys_dld_sym (loader_data, module, symbol)
01425 lt_user_data loader_data;
01426 lt_module module;
01427 const char *symbol;
01428 {
01429 lt_ptr address = dld_get_func (symbol);
01430
01431 if (!address)
01432 {
01433 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01434 }
01435
01436 return address;
01437 }
01438
01439 static struct lt_user_dlloader sys_dld = {
01440 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
01441 };
01442
01443 #endif
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 typedef struct lt_dlsymlists_t
01454 {
01455 struct lt_dlsymlists_t *next;
01456 const lt_dlsymlist *syms;
01457 } lt_dlsymlists_t;
01458
01459 static const lt_dlsymlist *default_preloaded_symbols = 0;
01460 static lt_dlsymlists_t *preloaded_symbols = 0;
01461
01462 static int
01463 presym_init (loader_data)
01464 lt_user_data loader_data;
01465 {
01466 int errors = 0;
01467
01468 LT_DLMUTEX_LOCK ();
01469
01470 preloaded_symbols = 0;
01471 if (default_preloaded_symbols)
01472 {
01473 errors = lt_dlpreload (default_preloaded_symbols);
01474 }
01475
01476 LT_DLMUTEX_UNLOCK ();
01477
01478 return errors;
01479 }
01480
01481 static int
01482 presym_free_symlists ()
01483 {
01484 lt_dlsymlists_t *lists;
01485
01486 LT_DLMUTEX_LOCK ();
01487
01488 lists = preloaded_symbols;
01489 while (lists)
01490 {
01491 lt_dlsymlists_t *tmp = lists;
01492
01493 lists = lists->next;
01494 LT_DLFREE (tmp);
01495 }
01496 preloaded_symbols = 0;
01497
01498 LT_DLMUTEX_UNLOCK ();
01499
01500 return 0;
01501 }
01502
01503 static int
01504 presym_exit (loader_data)
01505 lt_user_data loader_data;
01506 {
01507 presym_free_symlists ();
01508 return 0;
01509 }
01510
01511 static int
01512 presym_add_symlist (preloaded)
01513 const lt_dlsymlist *preloaded;
01514 {
01515 lt_dlsymlists_t *tmp;
01516 lt_dlsymlists_t *lists;
01517 int errors = 0;
01518
01519 LT_DLMUTEX_LOCK ();
01520
01521 lists = preloaded_symbols;
01522 while (lists)
01523 {
01524 if (lists->syms == preloaded)
01525 {
01526 goto done;
01527 }
01528 lists = lists->next;
01529 }
01530
01531 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
01532 if (tmp)
01533 {
01534 memset (tmp, 0, sizeof(lt_dlsymlists_t));
01535 tmp->syms = preloaded;
01536 tmp->next = preloaded_symbols;
01537 preloaded_symbols = tmp;
01538 }
01539 else
01540 {
01541 ++errors;
01542 }
01543
01544 done:
01545 LT_DLMUTEX_UNLOCK ();
01546 return errors;
01547 }
01548
01549 static lt_module
01550 presym_open (loader_data, filename)
01551 lt_user_data loader_data;
01552 const char *filename;
01553 {
01554 lt_dlsymlists_t *lists;
01555 lt_module module = (lt_module) 0;
01556
01557 LT_DLMUTEX_LOCK ();
01558 lists = preloaded_symbols;
01559
01560 if (!lists)
01561 {
01562 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
01563 goto done;
01564 }
01565
01566
01567
01568
01569
01570 if (!filename)
01571 {
01572 filename = "@PROGRAM@";
01573 }
01574
01575 while (lists)
01576 {
01577 const lt_dlsymlist *syms = lists->syms;
01578
01579 while (syms->name)
01580 {
01581 if (!syms->address && strcmp(syms->name, filename) == 0)
01582 {
01583 module = (lt_module) syms;
01584 goto done;
01585 }
01586 ++syms;
01587 }
01588
01589 lists = lists->next;
01590 }
01591
01592 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
01593
01594 done:
01595 LT_DLMUTEX_UNLOCK ();
01596 return module;
01597 }
01598
01599 static int
01600 presym_close (loader_data, module)
01601 lt_user_data loader_data;
01602 lt_module module;
01603 {
01604
01605 module = 0;
01606 return 0;
01607 }
01608
01609 static lt_ptr
01610 presym_sym (loader_data, module, symbol)
01611 lt_user_data loader_data;
01612 lt_module module;
01613 const char *symbol;
01614 {
01615 lt_dlsymlist *syms = (lt_dlsymlist*) module;
01616
01617 ++syms;
01618 while (syms->address)
01619 {
01620 if (strcmp(syms->name, symbol) == 0)
01621 {
01622 return syms->address;
01623 }
01624
01625 ++syms;
01626 }
01627
01628 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01629
01630 return 0;
01631 }
01632
01633 static struct lt_user_dlloader presym = {
01634 0, presym_open, presym_close, presym_sym, presym_exit, 0
01635 };
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
01646 lt_ptr data2));
01647
01648 static int foreach_dirinpath LT_PARAMS((const char *search_path,
01649 const char *base_name,
01650 foreach_callback_func *func,
01651 lt_ptr data1, lt_ptr data2));
01652
01653 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
01654 lt_ptr ignored));
01655 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
01656 lt_ptr ignored));
01657 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
01658 lt_ptr data2));
01659
01660
01661 static int canonicalize_path LT_PARAMS((const char *path,
01662 char **pcanonical));
01663 static int argzize_path LT_PARAMS((const char *path,
01664 char **pargz,
01665 size_t *pargz_len));
01666 static FILE *find_file LT_PARAMS((const char *search_path,
01667 const char *base_name,
01668 char **pdir));
01669 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
01670 const char *base_name,
01671 lt_dlhandle *handle));
01672 static int find_module LT_PARAMS((lt_dlhandle *handle,
01673 const char *dir,
01674 const char *libdir,
01675 const char *dlname,
01676 const char *old_name,
01677 int installed));
01678 static int free_vars LT_PARAMS((char *dlname, char *oldname,
01679 char *libdir, char *deplibs));
01680 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
01681 char *deplibs));
01682 static int trim LT_PARAMS((char **dest,
01683 const char *str));
01684 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
01685 const char *filename));
01686 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
01687 const char *filename));
01688 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
01689 static int lt_argz_insert LT_PARAMS((char **pargz,
01690 size_t *pargz_len,
01691 char *before,
01692 const char *entry));
01693 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
01694 size_t *pargz_len,
01695 const char *entry));
01696 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
01697 char *before,
01698 const char *dir));
01699
01700 static char *user_search_path= 0;
01701 static lt_dlloader *loaders = 0;
01702 static lt_dlhandle handles = 0;
01703 static int initialized = 0;
01704
01705
01706 int
01707 lt_dlinit ()
01708 {
01709 int errors = 0;
01710
01711 LT_DLMUTEX_LOCK ();
01712
01713
01714 if (++initialized == 1)
01715 {
01716 handles = 0;
01717 user_search_path = 0;
01718
01719 #if HAVE_LIBDL && !defined(__CYGWIN__)
01720 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
01721 #endif
01722 #if HAVE_SHL_LOAD
01723 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
01724 #endif
01725 #ifdef __WINDOWS__
01726 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
01727 #endif
01728 #ifdef __BEOS__
01729 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
01730 #endif
01731 #if HAVE_DLD
01732 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
01733 #endif
01734 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
01735
01736 if (presym_init (presym.dlloader_data))
01737 {
01738 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
01739 ++errors;
01740 }
01741 else if (errors != 0)
01742 {
01743 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
01744 ++errors;
01745 }
01746 }
01747
01748 LT_DLMUTEX_UNLOCK ();
01749
01750 return errors;
01751 }
01752
01753 int
01754 lt_dlpreload (preloaded)
01755 const lt_dlsymlist *preloaded;
01756 {
01757 int errors = 0;
01758
01759 if (preloaded)
01760 {
01761 errors = presym_add_symlist (preloaded);
01762 }
01763 else
01764 {
01765 presym_free_symlists();
01766
01767 LT_DLMUTEX_LOCK ();
01768 if (default_preloaded_symbols)
01769 {
01770 errors = lt_dlpreload (default_preloaded_symbols);
01771 }
01772 LT_DLMUTEX_UNLOCK ();
01773 }
01774
01775 return errors;
01776 }
01777
01778 int
01779 lt_dlpreload_default (preloaded)
01780 const lt_dlsymlist *preloaded;
01781 {
01782 LT_DLMUTEX_LOCK ();
01783 default_preloaded_symbols = preloaded;
01784 LT_DLMUTEX_UNLOCK ();
01785 return 0;
01786 }
01787
01788 int
01789 lt_dlexit ()
01790 {
01791
01792 lt_dlloader *loader;
01793 int errors = 0;
01794
01795 LT_DLMUTEX_LOCK ();
01796 loader = loaders;
01797
01798 if (!initialized)
01799 {
01800 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
01801 ++errors;
01802 goto done;
01803 }
01804
01805
01806 if (--initialized == 0)
01807 {
01808 int level;
01809
01810 while (handles && LT_DLIS_RESIDENT (handles))
01811 {
01812 handles = handles->next;
01813 }
01814
01815
01816 for (level = 1; handles; ++level)
01817 {
01818 lt_dlhandle cur = handles;
01819 int saw_nonresident = 0;
01820
01821 while (cur)
01822 {
01823 lt_dlhandle tmp = cur;
01824 cur = cur->next;
01825 if (!LT_DLIS_RESIDENT (tmp))
01826 saw_nonresident = 1;
01827 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
01828 {
01829 if (lt_dlclose (tmp))
01830 {
01831 ++errors;
01832 }
01833 }
01834 }
01835
01836 if (!saw_nonresident)
01837 break;
01838 }
01839
01840
01841 while (loader)
01842 {
01843 lt_dlloader *next = loader->next;
01844 lt_user_data data = loader->dlloader_data;
01845 if (loader->dlloader_exit && loader->dlloader_exit (data))
01846 {
01847 ++errors;
01848 }
01849
01850 LT_DLMEM_REASSIGN (loader, next);
01851 }
01852 loaders = 0;
01853 }
01854
01855 done:
01856 LT_DLMUTEX_UNLOCK ();
01857 return errors;
01858 }
01859
01860 static int
01861 tryall_dlopen (handle, filename)
01862 lt_dlhandle *handle;
01863 const char *filename;
01864 {
01865 lt_dlhandle cur;
01866 lt_dlloader *loader;
01867 const char *saved_error;
01868 int errors = 0;
01869
01870 LT_DLMUTEX_GETERROR (saved_error);
01871 LT_DLMUTEX_LOCK ();
01872
01873 cur = handles;
01874 loader = loaders;
01875
01876
01877 while (cur)
01878 {
01879
01880 if (!cur->info.filename && !filename)
01881 {
01882 break;
01883 }
01884
01885 if (cur->info.filename && filename
01886 && strcmp (cur->info.filename, filename) == 0)
01887 {
01888 break;
01889 }
01890
01891 cur = cur->next;
01892 }
01893
01894 if (cur)
01895 {
01896 ++cur->info.ref_count;
01897 *handle = cur;
01898 goto done;
01899 }
01900
01901 cur = *handle;
01902 if (filename)
01903 {
01904 cur->info.filename = lt_estrdup (filename);
01905 if (!cur->info.filename)
01906 {
01907 ++errors;
01908 goto done;
01909 }
01910 }
01911 else
01912 {
01913 cur->info.filename = 0;
01914 }
01915
01916 while (loader)
01917 {
01918 lt_user_data data = loader->dlloader_data;
01919
01920 cur->module = loader->module_open (data, filename);
01921
01922 if (cur->module != 0)
01923 {
01924 break;
01925 }
01926 loader = loader->next;
01927 }
01928
01929 if (!loader)
01930 {
01931 LT_DLFREE (cur->info.filename);
01932 ++errors;
01933 goto done;
01934 }
01935
01936 cur->loader = loader;
01937 LT_DLMUTEX_SETERROR (saved_error);
01938
01939 done:
01940 LT_DLMUTEX_UNLOCK ();
01941
01942 return errors;
01943 }
01944
01945 static int
01946 tryall_dlopen_module (handle, prefix, dirname, dlname)
01947 lt_dlhandle *handle;
01948 const char *prefix;
01949 const char *dirname;
01950 const char *dlname;
01951 {
01952 int error = 0;
01953 char *filename = 0;
01954 size_t filename_len = 0;
01955 size_t dirname_len = LT_STRLEN (dirname);
01956
01957 assert (handle);
01958 assert (dirname);
01959 assert (dlname);
01960 #ifdef LT_DIRSEP_CHAR
01961
01962
01963 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
01964 #endif
01965
01966 if (dirname[dirname_len -1] == '/')
01967 --dirname_len;
01968 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
01969
01970
01971
01972 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
01973 if (!filename)
01974 return 1;
01975
01976 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
01977
01978
01979
01980
01981 if (prefix)
01982 {
01983 error += tryall_dlopen_module (handle,
01984 (const char *) 0, prefix, filename);
01985 }
01986 else if (tryall_dlopen (handle, filename) != 0)
01987 {
01988 ++error;
01989 }
01990
01991 LT_DLFREE (filename);
01992 return error;
01993 }
01994
01995 static int
01996 find_module (handle, dir, libdir, dlname, old_name, installed)
01997 lt_dlhandle *handle;
01998 const char *dir;
01999 const char *libdir;
02000 const char *dlname;
02001 const char *old_name;
02002 int installed;
02003 {
02004
02005
02006
02007 if (old_name && tryall_dlopen (handle, old_name) == 0)
02008 {
02009 return 0;
02010 }
02011
02012
02013 if (dlname)
02014 {
02015
02016 if (installed && libdir)
02017 {
02018 if (tryall_dlopen_module (handle,
02019 (const char *) 0, libdir, dlname) == 0)
02020 return 0;
02021 }
02022
02023
02024 if (!installed)
02025 {
02026 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
02027 return 0;
02028 }
02029
02030
02031 {
02032 if (tryall_dlopen_module (handle,
02033 (const char *) 0, dir, dlname) == 0)
02034 return 0;
02035 }
02036 }
02037
02038 return 1;
02039 }
02040
02041
02042 static int
02043 canonicalize_path (path, pcanonical)
02044 const char *path;
02045 char **pcanonical;
02046 {
02047 char *canonical = 0;
02048
02049 assert (path && *path);
02050 assert (pcanonical);
02051
02052 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
02053 if (!canonical)
02054 return 1;
02055
02056 {
02057 size_t dest = 0;
02058 size_t src;
02059 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
02060 {
02061
02062
02063
02064 if (path[src] == LT_PATHSEP_CHAR)
02065 {
02066 if ((dest == 0)
02067 || (path[1+ src] == LT_PATHSEP_CHAR)
02068 || (path[1+ src] == LT_EOS_CHAR))
02069 continue;
02070 }
02071
02072
02073 if ((path[src] != '/')
02074 #ifdef LT_DIRSEP_CHAR
02075 && (path[src] != LT_DIRSEP_CHAR)
02076 #endif
02077 )
02078 {
02079 canonical[dest++] = path[src];
02080 }
02081
02082
02083
02084 else if ((path[1+ src] != LT_PATHSEP_CHAR)
02085 && (path[1+ src] != LT_EOS_CHAR)
02086 #ifdef LT_DIRSEP_CHAR
02087 && (path[1+ src] != LT_DIRSEP_CHAR)
02088 #endif
02089 && (path[1+ src] != '/'))
02090 {
02091 canonical[dest++] = '/';
02092 }
02093 }
02094
02095
02096 canonical[dest] = LT_EOS_CHAR;
02097 }
02098
02099
02100 *pcanonical = canonical;
02101
02102 return 0;
02103 }
02104
02105 static int
02106 argzize_path (path, pargz, pargz_len)
02107 const char *path;
02108 char **pargz;
02109 size_t *pargz_len;
02110 {
02111 error_t error;
02112
02113 assert (path);
02114 assert (pargz);
02115 assert (pargz_len);
02116
02117 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
02118 {
02119 switch (error)
02120 {
02121 case ENOMEM:
02122 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
02123 break;
02124 default:
02125 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
02126 break;
02127 }
02128
02129 return 1;
02130 }
02131
02132 return 0;
02133 }
02134
02135
02136
02137
02138
02139 static int
02140 foreach_dirinpath (search_path, base_name, func, data1, data2)
02141 const char *search_path;
02142 const char *base_name;
02143 foreach_callback_func *func;
02144 lt_ptr data1;
02145 lt_ptr data2;
02146 {
02147 int result = 0;
02148 int filenamesize = 0;
02149 int lenbase = LT_STRLEN (base_name);
02150 size_t argz_len = 0;
02151 char * argz = 0;
02152 char * filename = 0;
02153 char * canonical = 0;
02154
02155 LT_DLMUTEX_LOCK ();
02156
02157 if (!search_path || !*search_path)
02158 {
02159 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02160 goto cleanup;
02161 }
02162
02163 if (canonicalize_path (search_path, &canonical) != 0)
02164 goto cleanup;
02165
02166 if (argzize_path (canonical, &argz, &argz_len) != 0)
02167 goto cleanup;
02168
02169 {
02170 char *dir_name = 0;
02171 while ((dir_name = argz_next (argz, argz_len, dir_name)))
02172 {
02173 int lendir = LT_STRLEN (dir_name);
02174
02175 if (lendir +1 +lenbase >= filenamesize)
02176 {
02177 LT_DLFREE (filename);
02178 filenamesize = lendir +1 +lenbase +1;
02179 filename = LT_EMALLOC (char, filenamesize);
02180 if (!filename)
02181 goto cleanup;
02182 }
02183
02184 strncpy (filename, dir_name, lendir);
02185 if (base_name && *base_name)
02186 {
02187 if (filename[lendir -1] != '/')
02188 filename[lendir++] = '/';
02189 strcpy (filename +lendir, base_name);
02190 }
02191
02192 if ((result = (*func) (filename, data1, data2)))
02193 {
02194 break;
02195 }
02196 }
02197 }
02198
02199 cleanup:
02200 LT_DLFREE (argz);
02201 LT_DLFREE (canonical);
02202 LT_DLFREE (filename);
02203
02204 LT_DLMUTEX_UNLOCK ();
02205
02206 return result;
02207 }
02208
02209
02210
02211
02212 static int
02213 find_file_callback (filename, data1, data2)
02214 char *filename;
02215 lt_ptr data1;
02216 lt_ptr data2;
02217 {
02218 char **pdir = (char **) data1;
02219 FILE **pfile = (FILE **) data2;
02220 int is_done = 0;
02221
02222 assert (filename && *filename);
02223 assert (pdir);
02224 assert (pfile);
02225
02226 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
02227 {
02228 char *dirend = strrchr (filename, '/');
02229
02230 if (dirend > filename)
02231 *dirend = LT_EOS_CHAR;
02232
02233 LT_DLFREE (*pdir);
02234 *pdir = lt_estrdup (filename);
02235 is_done = (*pdir == 0) ? -1 : 1;
02236 }
02237
02238 return is_done;
02239 }
02240
02241 static FILE *
02242 find_file (search_path, base_name, pdir)
02243 const char *search_path;
02244 const char *base_name;
02245 char **pdir;
02246 {
02247 FILE *file = 0;
02248
02249 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
02250
02251 return file;
02252 }
02253
02254 static int
02255 find_handle_callback (filename, data, ignored)
02256 char *filename;
02257 lt_ptr data;
02258 lt_ptr ignored;
02259 {
02260 lt_dlhandle *handle = (lt_dlhandle *) data;
02261 int found = access (filename, R_OK);
02262
02263
02264 if (!found)
02265 return 0;
02266
02267
02268
02269 if (tryall_dlopen (handle, filename) != 0)
02270 *handle = 0;
02271
02272 return 1;
02273 }
02274
02275
02276
02277 static lt_dlhandle *
02278 find_handle (search_path, base_name, handle)
02279 const char *search_path;
02280 const char *base_name;
02281 lt_dlhandle *handle;
02282 {
02283 if (!search_path)
02284 return 0;
02285
02286 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
02287 handle, 0))
02288 return 0;
02289
02290 return handle;
02291 }
02292
02293 static int
02294 load_deplibs (handle, deplibs)
02295 lt_dlhandle handle;
02296 char *deplibs;
02297 {
02298 #if LTDL_DLOPEN_DEPLIBS
02299 char *p, *save_search_path = 0;
02300 int depcount = 0;
02301 int i;
02302 char **names = 0;
02303 #endif
02304 int errors = 0;
02305
02306 handle->depcount = 0;
02307
02308 #if LTDL_DLOPEN_DEPLIBS
02309 if (!deplibs)
02310 {
02311 return errors;
02312 }
02313 ++errors;
02314
02315 LT_DLMUTEX_LOCK ();
02316 if (user_search_path)
02317 {
02318 save_search_path = lt_estrdup (user_search_path);
02319 if (!save_search_path)
02320 goto cleanup;
02321 }
02322
02323
02324 p = deplibs;
02325 while (*p)
02326 {
02327 if (!isspace ((int) *p))
02328 {
02329 char *end = p+1;
02330 while (*end && !isspace((int) *end))
02331 {
02332 ++end;
02333 }
02334
02335 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
02336 {
02337 char save = *end;
02338 *end = 0;
02339 if (lt_dladdsearchdir(p+2))
02340 {
02341 goto cleanup;
02342 }
02343 *end = save;
02344 }
02345 else
02346 {
02347 ++depcount;
02348 }
02349
02350 p = end;
02351 }
02352 else
02353 {
02354 ++p;
02355 }
02356 }
02357
02358
02359 LT_DLFREE (user_search_path);
02360 user_search_path = save_search_path;
02361
02362 LT_DLMUTEX_UNLOCK ();
02363
02364 if (!depcount)
02365 {
02366 errors = 0;
02367 goto cleanup;
02368 }
02369
02370 names = LT_EMALLOC (char *, depcount * sizeof (char*));
02371 if (!names)
02372 goto cleanup;
02373
02374
02375 depcount = 0;
02376 p = deplibs;
02377 while (*p)
02378 {
02379 if (isspace ((int) *p))
02380 {
02381 ++p;
02382 }
02383 else
02384 {
02385 char *end = p+1;
02386 while (*end && !isspace ((int) *end))
02387 {
02388 ++end;
02389 }
02390
02391 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
02392 {
02393 char *name;
02394 char save = *end;
02395 *end = 0;
02396 if (strncmp(p, "-l", 2) == 0)
02397 {
02398 size_t name_len = 3+ LT_STRLEN (p + 2);
02399 name = LT_EMALLOC (char, 1+ name_len);
02400 if (name)
02401 sprintf (name, "lib%s", p+2);
02402 }
02403 else
02404 name = lt_estrdup(p);
02405
02406 if (!name)
02407 goto cleanup_names;
02408
02409 names[depcount++] = name;
02410 *end = save;
02411 }
02412 p = end;
02413 }
02414 }
02415
02416
02417
02418
02419
02420
02421 if (depcount)
02422 {
02423 int j = 0;
02424
02425 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
02426 if (!handle->deplibs)
02427 goto cleanup;
02428
02429 for (i = 0; i < depcount; ++i)
02430 {
02431 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
02432 if (handle->deplibs[j])
02433 {
02434 ++j;
02435 }
02436 }
02437
02438 handle->depcount = j;
02439 errors = 0;
02440 }
02441
02442 cleanup_names:
02443 for (i = 0; i < depcount; ++i)
02444 {
02445 LT_DLFREE (names[i]);
02446 }
02447
02448 cleanup:
02449 LT_DLFREE (names);
02450 #endif
02451
02452 return errors;
02453 }
02454
02455 static int
02456 unload_deplibs (handle)
02457 lt_dlhandle handle;
02458 {
02459 int i;
02460 int errors = 0;
02461
02462 if (handle->depcount)
02463 {
02464 for (i = 0; i < handle->depcount; ++i)
02465 {
02466 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
02467 {
02468 errors += lt_dlclose (handle->deplibs[i]);
02469 }
02470 }
02471 }
02472
02473 return errors;
02474 }
02475
02476 static int
02477 trim (dest, str)
02478 char **dest;
02479 const char *str;
02480 {
02481
02482
02483 const char *end = strrchr (str, '\'');
02484 int len = LT_STRLEN (str);
02485 char *tmp;
02486
02487 LT_DLFREE (*dest);
02488
02489 if (len > 3 && str[0] == '\'')
02490 {
02491 tmp = LT_EMALLOC (char, end - str);
02492 if (!tmp)
02493 return 1;
02494
02495 strncpy(tmp, &str[1], (end - str) - 1);
02496 tmp[len-3] = LT_EOS_CHAR;
02497 *dest = tmp;
02498 }
02499 else
02500 {
02501 *dest = 0;
02502 }
02503
02504 return 0;
02505 }
02506
02507 static int
02508 free_vars (dlname, oldname, libdir, deplibs)
02509 char *dlname;
02510 char *oldname;
02511 char *libdir;
02512 char *deplibs;
02513 {
02514 LT_DLFREE (dlname);
02515 LT_DLFREE (oldname);
02516 LT_DLFREE (libdir);
02517 LT_DLFREE (deplibs);
02518
02519 return 0;
02520 }
02521
02522 int
02523 try_dlopen (phandle, filename)
02524 lt_dlhandle *phandle;
02525 const char *filename;
02526 {
02527 const char * ext = 0;
02528 const char * saved_error = 0;
02529 char * canonical = 0;
02530 char * base_name = 0;
02531 char * dir = 0;
02532 char * name = 0;
02533 int errors = 0;
02534 lt_dlhandle newhandle;
02535
02536 assert (phandle);
02537 assert (*phandle == 0);
02538
02539 LT_DLMUTEX_GETERROR (saved_error);
02540
02541
02542 if (!filename)
02543 {
02544 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
02545 if (*phandle == 0)
02546 return 1;
02547
02548 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
02549 newhandle = *phandle;
02550
02551
02552 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
02553
02554 if (tryall_dlopen (&newhandle, 0) != 0)
02555 {
02556 LT_DLFREE (*phandle);
02557 return 1;
02558 }
02559
02560 goto register_handle;
02561 }
02562
02563 assert (filename && *filename);
02564
02565
02566
02567 if (canonicalize_path (filename, &canonical) != 0)
02568 {
02569 ++errors;
02570 goto cleanup;
02571 }
02572
02573
02574
02575 base_name = strrchr (canonical, '/');
02576 if (base_name)
02577 {
02578 size_t dirlen = (1+ base_name) - canonical;
02579
02580 dir = LT_EMALLOC (char, 1+ dirlen);
02581 if (!dir)
02582 {
02583 ++errors;
02584 goto cleanup;
02585 }
02586
02587 strncpy (dir, canonical, dirlen);
02588 dir[dirlen] = LT_EOS_CHAR;
02589
02590 ++base_name;
02591 }
02592 else
02593 LT_DLMEM_REASSIGN (base_name, canonical);
02594
02595 assert (base_name && *base_name);
02596
02597
02598 ext = strrchr (base_name, '.');
02599 if (ext && strcmp (ext, archive_ext) == 0)
02600 {
02601
02602 FILE * file = 0;
02603 char * dlname = 0;
02604 char * old_name = 0;
02605 char * libdir = 0;
02606 char * deplibs = 0;
02607 char * line = 0;
02608 size_t line_len;
02609 int i;
02610
02611
02612
02613
02614 int installed = 1;
02615
02616
02617 name = LT_EMALLOC (char, ext - base_name + 1);
02618 if (!name)
02619 {
02620 ++errors;
02621 goto cleanup;
02622 }
02623
02624
02625 for (i = 0; i < ext - base_name; ++i)
02626 {
02627 if (isalnum ((int)(base_name[i])))
02628 {
02629 name[i] = base_name[i];
02630 }
02631 else
02632 {
02633 name[i] = '_';
02634 }
02635 }
02636 name[ext - base_name] = LT_EOS_CHAR;
02637
02638
02639
02640
02641
02642 if (!dir)
02643 {
02644 const char *search_path;
02645
02646 LT_DLMUTEX_LOCK ();
02647 search_path = user_search_path;
02648 if (search_path)
02649 file = find_file (user_search_path, base_name, &dir);
02650 LT_DLMUTEX_UNLOCK ();
02651
02652 if (!file)
02653 {
02654 search_path = getenv (LTDL_SEARCHPATH_VAR);
02655 if (search_path)
02656 file = find_file (search_path, base_name, &dir);
02657 }
02658
02659 #ifdef LTDL_SHLIBPATH_VAR
02660 if (!file)
02661 {
02662 search_path = getenv (LTDL_SHLIBPATH_VAR);
02663 if (search_path)
02664 file = find_file (search_path, base_name, &dir);
02665 }
02666 #endif
02667 #ifdef LTDL_SYSSEARCHPATH
02668 if (!file && sys_search_path)
02669 {
02670 file = find_file (sys_search_path, base_name, &dir);
02671 }
02672 #endif
02673 }
02674 if (!file)
02675 {
02676 file = fopen (filename, LT_READTEXT_MODE);
02677 }
02678
02679
02680
02681 if (!file)
02682 {
02683 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02684 ++errors;
02685 goto cleanup;
02686 }
02687
02688 line_len = LT_FILENAME_MAX;
02689 line = LT_EMALLOC (char, line_len);
02690 if (!line)
02691 {
02692 fclose (file);
02693 ++errors;
02694 goto cleanup;
02695 }
02696
02697
02698 while (!feof (file))
02699 {
02700 if (!fgets (line, line_len, file))
02701 {
02702 break;
02703 }
02704
02705
02706
02707 while (line[LT_STRLEN(line) -1] != '\n')
02708 {
02709 line = LT_DLREALLOC (char, line, line_len *2);
02710 if (!fgets (&line[line_len -1], line_len +1, file))
02711 {
02712 break;
02713 }
02714 line_len *= 2;
02715 }
02716
02717 if (line[0] == '\n' || line[0] == '#')
02718 {
02719 continue;
02720 }
02721
02722 #undef STR_DLNAME
02723 #define STR_DLNAME "dlname="
02724 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
02725 {
02726 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
02727 }
02728
02729 #undef STR_OLD_LIBRARY
02730 #define STR_OLD_LIBRARY "old_library="
02731 else if (strncmp (line, STR_OLD_LIBRARY,
02732 sizeof (STR_OLD_LIBRARY) - 1) == 0)
02733 {
02734 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
02735 }
02736 #undef STR_LIBDIR
02737 #define STR_LIBDIR "libdir="
02738 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
02739 {
02740 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
02741 }
02742
02743 #undef STR_DL_DEPLIBS
02744 #define STR_DL_DEPLIBS "dependency_libs="
02745 else if (strncmp (line, STR_DL_DEPLIBS,
02746 sizeof (STR_DL_DEPLIBS) - 1) == 0)
02747 {
02748 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
02749 }
02750 else if (strcmp (line, "installed=yes\n") == 0)
02751 {
02752 installed = 1;
02753 }
02754 else if (strcmp (line, "installed=no\n") == 0)
02755 {
02756 installed = 0;
02757 }
02758
02759 #undef STR_LIBRARY_NAMES
02760 #define STR_LIBRARY_NAMES "library_names="
02761 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
02762 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
02763 {
02764 char *last_libname;
02765 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
02766 if (!errors
02767 && dlname
02768 && (last_libname = strrchr (dlname, ' ')) != 0)
02769 {
02770 last_libname = lt_estrdup (last_libname + 1);
02771 if (!last_libname)
02772 {
02773 ++errors;
02774 goto cleanup;
02775 }
02776 LT_DLMEM_REASSIGN (dlname, last_libname);
02777 }
02778 }
02779
02780 if (errors)
02781 break;
02782 }
02783
02784 fclose (file);
02785 LT_DLFREE (line);
02786
02787
02788 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
02789 if (*phandle == 0)
02790 ++errors;
02791
02792 if (errors)
02793 {
02794 free_vars (dlname, old_name, libdir, deplibs);
02795 LT_DLFREE (*phandle);
02796 goto cleanup;
02797 }
02798
02799 assert (*phandle);
02800
02801 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
02802 if (load_deplibs (*phandle, deplibs) == 0)
02803 {
02804 newhandle = *phandle;
02805
02806 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
02807 {
02808 unload_deplibs (*phandle);
02809 ++errors;
02810 }
02811 }
02812 else
02813 {
02814 ++errors;
02815 }
02816
02817 free_vars (dlname, old_name, libdir, deplibs);
02818 if (errors)
02819 {
02820 LT_DLFREE (*phandle);
02821 goto cleanup;
02822 }
02823
02824 if (*phandle != newhandle)
02825 {
02826 unload_deplibs (*phandle);
02827 }
02828 }
02829 else
02830 {
02831
02832 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
02833 if (*phandle == 0)
02834 {
02835 ++errors;
02836 goto cleanup;
02837 }
02838
02839 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
02840 newhandle = *phandle;
02841
02842
02843
02844
02845
02846 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
02847 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
02848 &newhandle)
02849 #ifdef LTDL_SHLIBPATH_VAR
02850 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
02851 &newhandle)
02852 #endif
02853 #ifdef LTDL_SYSSEARCHPATH
02854 && !find_handle (sys_search_path, base_name, &newhandle)
02855 #endif
02856 )))
02857 {
02858 if (0 != tryall_dlopen (&newhandle, filename))
02859 newhandle = 0;
02860 }
02861
02862 if (!newhandle)
02863 {
02864 LT_DLFREE (*phandle);
02865 ++errors;
02866 goto cleanup;
02867 }
02868 }
02869
02870 register_handle:
02871 LT_DLMEM_REASSIGN (*phandle, newhandle);
02872
02873 if ((*phandle)->info.ref_count == 0)
02874 {
02875 (*phandle)->info.ref_count = 1;
02876 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
02877
02878 LT_DLMUTEX_LOCK ();
02879 (*phandle)->next = handles;
02880 handles = *phandle;
02881 LT_DLMUTEX_UNLOCK ();
02882 }
02883
02884 LT_DLMUTEX_SETERROR (saved_error);
02885
02886 cleanup:
02887 LT_DLFREE (dir);
02888 LT_DLFREE (name);
02889 LT_DLFREE (canonical);
02890
02891 return errors;
02892 }
02893
02894 lt_dlhandle
02895 lt_dlopen (filename)
02896 const char *filename;
02897 {
02898 lt_dlhandle handle = 0;
02899
02900
02901
02902 if (try_dlopen (&handle, filename) != 0)
02903 return 0;
02904
02905 return handle;
02906 }
02907
02908
02909
02910 int
02911 file_not_found ()
02912 {
02913 const char *error = 0;
02914
02915 LT_DLMUTEX_GETERROR (error);
02916 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
02917 return 1;
02918
02919 return 0;
02920 }
02921
02922
02923
02924
02925
02926 lt_dlhandle
02927 lt_dlopenext (filename)
02928 const char *filename;
02929 {
02930 lt_dlhandle handle = 0;
02931 char * tmp = 0;
02932 char * ext = 0;
02933 int len;
02934 int errors = 0;
02935 int file_found = 1;
02936
02937 if (!filename)
02938 {
02939 return lt_dlopen (filename);
02940 }
02941
02942 assert (filename);
02943
02944 len = LT_STRLEN (filename);
02945 ext = strrchr (filename, '.');
02946
02947
02948
02949 if (ext && ((strcmp (ext, archive_ext) == 0)
02950 #ifdef LTDL_SHLIB_EXT
02951 || (strcmp (ext, shlib_ext) == 0)
02952 #endif
02953 ))
02954 {
02955 return lt_dlopen (filename);
02956 }
02957
02958
02959 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
02960 if (!tmp)
02961 return 0;
02962
02963 strcpy (tmp, filename);
02964 strcat (tmp, archive_ext);
02965 errors = try_dlopen (&handle, tmp);
02966
02967
02968
02969
02970
02971
02972 if (handle || ((errors > 0) && file_not_found ()))
02973 {
02974 LT_DLFREE (tmp);
02975 return handle;
02976 }
02977
02978 #ifdef LTDL_SHLIB_EXT
02979
02980 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
02981 {
02982 LT_DLFREE (tmp);
02983 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
02984 if (!tmp)
02985 return 0;
02986
02987 strcpy (tmp, filename);
02988 }
02989 else
02990 {
02991 tmp[len] = LT_EOS_CHAR;
02992 }
02993
02994 strcat(tmp, shlib_ext);
02995 errors = try_dlopen (&handle, tmp);
02996
02997
02998
02999 if (handle || ((errors > 0) && file_not_found ()))
03000 {
03001 LT_DLFREE (tmp);
03002 return handle;
03003 }
03004 #endif
03005
03006
03007
03008 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
03009 LT_DLFREE (tmp);
03010 return 0;
03011 }
03012
03013
03014 int
03015 lt_argz_insert (pargz, pargz_len, before, entry)
03016 char **pargz;
03017 size_t *pargz_len;
03018 char *before;
03019 const char *entry;
03020 {
03021 error_t error;
03022
03023 if ((error = argz_insert (pargz, pargz_len, before, entry)))
03024 {
03025 switch (error)
03026 {
03027 case ENOMEM:
03028 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
03029 break;
03030 default:
03031 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
03032 break;
03033 }
03034 return 1;
03035 }
03036
03037 return 0;
03038 }
03039
03040 int
03041 lt_argz_insertinorder (pargz, pargz_len, entry)
03042 char **pargz;
03043 size_t *pargz_len;
03044 const char *entry;
03045 {
03046 char *before = 0;
03047
03048 assert (pargz);
03049 assert (pargz_len);
03050 assert (entry && *entry);
03051
03052 if (*pargz)
03053 while ((before = argz_next (*pargz, *pargz_len, before)))
03054 {
03055 int cmp = strcmp (entry, before);
03056
03057 if (cmp < 0) break;
03058 if (cmp == 0) return 0;
03059 }
03060
03061 return lt_argz_insert (pargz, pargz_len, before, entry);
03062 }
03063
03064 int
03065 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
03066 char **pargz;
03067 size_t *pargz_len;
03068 const char *dirnam;
03069 struct dirent *dp;
03070 {
03071 char *buf = 0;
03072 size_t buf_len = 0;
03073 char *end = 0;
03074 size_t end_offset = 0;
03075 size_t dir_len = 0;
03076 int errors = 0;
03077
03078 assert (pargz);
03079 assert (pargz_len);
03080 assert (dp);
03081
03082 dir_len = LT_STRLEN (dirnam);
03083 end = dp->d_name + LT_D_NAMLEN(dp);
03084
03085
03086 {
03087 char *p;
03088 for (p = end; p -1 > dp->d_name; --p)
03089 if (strchr (".0123456789", p[-1]) == 0)
03090 break;
03091
03092 if (*p == '.')
03093 end = p;
03094 }
03095
03096
03097 {
03098 char *p;
03099 for (p = end -1; p > dp->d_name; --p)
03100 if (*p == '.')
03101 {
03102 end = p;
03103 break;
03104 }
03105 }
03106
03107
03108 end_offset = end - dp->d_name;
03109 buf_len = dir_len + 1+ end_offset;
03110 buf = LT_EMALLOC (char, 1+ buf_len);
03111 if (!buf)
03112 return ++errors;
03113
03114 assert (buf);
03115
03116 strcpy (buf, dirnam);
03117 strcat (buf, "/");
03118 strncat (buf, dp->d_name, end_offset);
03119 buf[buf_len] = LT_EOS_CHAR;
03120
03121
03122 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
03123 ++errors;
03124
03125 LT_DLFREE (buf);
03126
03127 return errors;
03128 }
03129
03130 int
03131 list_files_by_dir (dirnam, pargz, pargz_len)
03132 const char *dirnam;
03133 char **pargz;
03134 size_t *pargz_len;
03135 {
03136 DIR *dirp = 0;
03137 int errors = 0;
03138
03139 assert (dirnam && *dirnam);
03140 assert (pargz);
03141 assert (pargz_len);
03142 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
03143
03144 dirp = opendir (dirnam);
03145 if (dirp)
03146 {
03147 struct dirent *dp = 0;
03148
03149 while ((dp = readdir (dirp)))
03150 if (dp->d_name[0] != '.')
03151 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
03152 {
03153 ++errors;
03154 break;
03155 }
03156
03157 closedir (dirp);
03158 }
03159 else
03160 ++errors;
03161
03162 return errors;
03163 }
03164
03165
03166
03167
03168 static int
03169 foreachfile_callback (dirname, data1, data2)
03170 char *dirname;
03171 lt_ptr data1;
03172 lt_ptr data2;
03173 {
03174 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
03175 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
03176
03177 int is_done = 0;
03178 char *argz = 0;
03179 size_t argz_len = 0;
03180
03181 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
03182 goto cleanup;
03183 if (!argz)
03184 goto cleanup;
03185
03186 {
03187 char *filename = 0;
03188 while ((filename = argz_next (argz, argz_len, filename)))
03189 if ((is_done = (*func) (filename, data2)))
03190 break;
03191 }
03192
03193 cleanup:
03194 LT_DLFREE (argz);
03195
03196 return is_done;
03197 }
03198
03199
03200
03201
03202
03203
03204
03205
03206 int
03207 lt_dlforeachfile (search_path, func, data)
03208 const char *search_path;
03209 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
03210 lt_ptr data;
03211 {
03212 int is_done = 0;
03213
03214 if (search_path)
03215 {
03216
03217
03218 is_done = foreach_dirinpath (search_path, 0,
03219 foreachfile_callback, func, data);
03220 }
03221 else
03222 {
03223
03224 is_done = foreach_dirinpath (user_search_path, 0,
03225 foreachfile_callback, func, data);
03226 if (!is_done)
03227 {
03228 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
03229 foreachfile_callback, func, data);
03230 }
03231
03232 #ifdef LTDL_SHLIBPATH_VAR
03233 if (!is_done)
03234 {
03235 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
03236 foreachfile_callback, func, data);
03237 }
03238 #endif
03239 #ifdef LTDL_SYSSEARCHPATH
03240 if (!is_done)
03241 {
03242 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
03243 foreachfile_callback, func, data);
03244 }
03245 #endif
03246 }
03247
03248 return is_done;
03249 }
03250
03251 int
03252 lt_dlclose (handle)
03253 lt_dlhandle handle;
03254 {
03255 lt_dlhandle cur, last;
03256 int errors = 0;
03257
03258 LT_DLMUTEX_LOCK ();
03259
03260
03261 last = cur = handles;
03262 while (cur && handle != cur)
03263 {
03264 last = cur;
03265 cur = cur->next;
03266 }
03267
03268 if (!cur)
03269 {
03270 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03271 ++errors;
03272 goto done;
03273 }
03274
03275 handle->info.ref_count--;
03276
03277
03278
03279
03280
03281 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
03282 {
03283 lt_user_data data = handle->loader->dlloader_data;
03284
03285 if (handle != handles)
03286 {
03287 last->next = handle->next;
03288 }
03289 else
03290 {
03291 handles = handle->next;
03292 }
03293
03294 errors += handle->loader->module_close (data, handle->module);
03295 errors += unload_deplibs(handle);
03296
03297 LT_DLFREE (handle->info.filename);
03298 LT_DLFREE (handle->info.name);
03299 LT_DLFREE (handle);
03300
03301 goto done;
03302 }
03303
03304 if (LT_DLIS_RESIDENT (handle))
03305 {
03306 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
03307 ++errors;
03308 }
03309
03310 done:
03311 LT_DLMUTEX_UNLOCK ();
03312
03313 return errors;
03314 }
03315
03316 lt_ptr
03317 lt_dlsym (handle, symbol)
03318 lt_dlhandle handle;
03319 const char *symbol;
03320 {
03321 int lensym;
03322 char lsym[LT_SYMBOL_LENGTH];
03323 char *sym;
03324 lt_ptr address;
03325 lt_user_data data;
03326
03327 if (!handle)
03328 {
03329 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03330 return 0;
03331 }
03332
03333 if (!symbol)
03334 {
03335 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
03336 return 0;
03337 }
03338
03339 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
03340 + LT_STRLEN (handle->info.name);
03341
03342 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
03343 {
03344 sym = lsym;
03345 }
03346 else
03347 {
03348 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
03349 if (!sym)
03350 {
03351 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
03352 return 0;
03353 }
03354 }
03355
03356 data = handle->loader->dlloader_data;
03357 if (handle->info.name)
03358 {
03359 const char *saved_error;
03360
03361 LT_DLMUTEX_GETERROR (saved_error);
03362
03363
03364 if (handle->loader->sym_prefix)
03365 {
03366 strcpy(sym, handle->loader->sym_prefix);
03367 strcat(sym, handle->info.name);
03368 }
03369 else
03370 {
03371 strcpy(sym, handle->info.name);
03372 }
03373
03374 strcat(sym, "_LTX_");
03375 strcat(sym, symbol);
03376
03377
03378 address = handle->loader->find_sym (data, handle->module, sym);
03379 if (address)
03380 {
03381 if (sym != lsym)
03382 {
03383 LT_DLFREE (sym);
03384 }
03385 return address;
03386 }
03387 LT_DLMUTEX_SETERROR (saved_error);
03388 }
03389
03390
03391 if (handle->loader->sym_prefix)
03392 {
03393 strcpy(sym, handle->loader->sym_prefix);
03394 strcat(sym, symbol);
03395 }
03396 else
03397 {
03398 strcpy(sym, symbol);
03399 }
03400
03401 address = handle->loader->find_sym (data, handle->module, sym);
03402 if (sym != lsym)
03403 {
03404 LT_DLFREE (sym);
03405 }
03406
03407 return address;
03408 }
03409
03410 const char *
03411 lt_dlerror ()
03412 {
03413 const char *error;
03414
03415 LT_DLMUTEX_GETERROR (error);
03416 LT_DLMUTEX_SETERROR (0);
03417
03418 return error ? error : LT_DLSTRERROR (UNKNOWN);
03419 }
03420
03421 int
03422 lt_dlpath_insertdir (ppath, before, dir)
03423 char **ppath;
03424 char *before;
03425 const char *dir;
03426 {
03427 int errors = 0;
03428 char *canonical = 0;
03429 char *argz = 0;
03430 size_t argz_len = 0;
03431
03432 assert (ppath);
03433 assert (dir && *dir);
03434
03435 if (canonicalize_path (dir, &canonical) != 0)
03436 {
03437 ++errors;
03438 goto cleanup;
03439 }
03440
03441 assert (canonical && *canonical);
03442
03443
03444 if (*ppath == 0)
03445 {
03446 assert (!before);
03447 assert (dir);
03448
03449 *ppath = lt_estrdup (dir);
03450 if (*ppath == 0)
03451 ++errors;
03452
03453 return errors;
03454 }
03455
03456 assert (ppath && *ppath);
03457
03458 if (argzize_path (*ppath, &argz, &argz_len) != 0)
03459 {
03460 ++errors;
03461 goto cleanup;
03462 }
03463
03464
03465
03466
03467
03468
03469 if (before)
03470 {
03471 assert (*ppath <= before);
03472 assert (before - *ppath <= strlen (*ppath));
03473
03474 before = before - *ppath + argz;
03475 }
03476
03477 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
03478 {
03479 ++errors;
03480 goto cleanup;
03481 }
03482
03483 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
03484 LT_DLMEM_REASSIGN (*ppath, argz);
03485
03486 cleanup:
03487 LT_DLFREE (canonical);
03488 LT_DLFREE (argz);
03489
03490 return errors;
03491 }
03492
03493 int
03494 lt_dladdsearchdir (search_dir)
03495 const char *search_dir;
03496 {
03497 int errors = 0;
03498
03499 if (search_dir && *search_dir)
03500 {
03501 LT_DLMUTEX_LOCK ();
03502 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
03503 ++errors;
03504 LT_DLMUTEX_UNLOCK ();
03505 }
03506
03507 return errors;
03508 }
03509
03510 int
03511 lt_dlinsertsearchdir (before, search_dir)
03512 const char *before;
03513 const char *search_dir;
03514 {
03515 int errors = 0;
03516
03517 if (before)
03518 {
03519 LT_DLMUTEX_LOCK ();
03520 if ((before < user_search_path)
03521 || (before >= user_search_path + LT_STRLEN (user_search_path)))
03522 {
03523 LT_DLMUTEX_UNLOCK ();
03524 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
03525 return 1;
03526 }
03527 LT_DLMUTEX_UNLOCK ();
03528 }
03529
03530 if (search_dir && *search_dir)
03531 {
03532 LT_DLMUTEX_LOCK ();
03533 if (lt_dlpath_insertdir (&user_search_path,
03534 (char *) before, search_dir) != 0)
03535 {
03536 ++errors;
03537 }
03538 LT_DLMUTEX_UNLOCK ();
03539 }
03540
03541 return errors;
03542 }
03543
03544 int
03545 lt_dlsetsearchpath (search_path)
03546 const char *search_path;
03547 {
03548 int errors = 0;
03549
03550 LT_DLMUTEX_LOCK ();
03551 LT_DLFREE (user_search_path);
03552 LT_DLMUTEX_UNLOCK ();
03553
03554 if (!search_path || !LT_STRLEN (search_path))
03555 {
03556 return errors;
03557 }
03558
03559 LT_DLMUTEX_LOCK ();
03560 if (canonicalize_path (search_path, &user_search_path) != 0)
03561 ++errors;
03562 LT_DLMUTEX_UNLOCK ();
03563
03564 return errors;
03565 }
03566
03567 const char *
03568 lt_dlgetsearchpath ()
03569 {
03570 const char *saved_path;
03571
03572 LT_DLMUTEX_LOCK ();
03573 saved_path = user_search_path;
03574 LT_DLMUTEX_UNLOCK ();
03575
03576 return saved_path;
03577 }
03578
03579 int
03580 lt_dlmakeresident (handle)
03581 lt_dlhandle handle;
03582 {
03583 int errors = 0;
03584
03585 if (!handle)
03586 {
03587 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03588 ++errors;
03589 }
03590 else
03591 {
03592 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
03593 }
03594
03595 return errors;
03596 }
03597
03598 int
03599 lt_dlisresident (handle)
03600 lt_dlhandle handle;
03601 {
03602 if (!handle)
03603 {
03604 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03605 return -1;
03606 }
03607
03608 return LT_DLIS_RESIDENT (handle);
03609 }
03610
03611
03612
03613
03614
03615
03616 const lt_dlinfo *
03617 lt_dlgetinfo (handle)
03618 lt_dlhandle handle;
03619 {
03620 if (!handle)
03621 {
03622 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03623 return 0;
03624 }
03625
03626 return &(handle->info);
03627 }
03628
03629 lt_dlhandle
03630 lt_dlhandle_next (place)
03631 lt_dlhandle place;
03632 {
03633 return place ? place->next : handles;
03634 }
03635
03636 int
03637 lt_dlforeach (func, data)
03638 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
03639 lt_ptr data;
03640 {
03641 int errors = 0;
03642 lt_dlhandle cur;
03643
03644 LT_DLMUTEX_LOCK ();
03645
03646 cur = handles;
03647 while (cur)
03648 {
03649 lt_dlhandle tmp = cur;
03650
03651 cur = cur->next;
03652 if ((*func) (tmp, data))
03653 {
03654 ++errors;
03655 break;
03656 }
03657 }
03658
03659 LT_DLMUTEX_UNLOCK ();
03660
03661 return errors;
03662 }
03663
03664 lt_dlcaller_id
03665 lt_dlcaller_register ()
03666 {
03667 static lt_dlcaller_id last_caller_id = 0;
03668 int result;
03669
03670 LT_DLMUTEX_LOCK ();
03671 result = ++last_caller_id;
03672 LT_DLMUTEX_UNLOCK ();
03673
03674 return result;
03675 }
03676
03677 lt_ptr
03678 lt_dlcaller_set_data (key, handle, data)
03679 lt_dlcaller_id key;
03680 lt_dlhandle handle;
03681 lt_ptr data;
03682 {
03683 int n_elements = 0;
03684 lt_ptr stale = (lt_ptr) 0;
03685 int i;
03686
03687
03688
03689 LT_DLMUTEX_LOCK ();
03690
03691 if (handle->caller_data)
03692 while (handle->caller_data[n_elements].key)
03693 ++n_elements;
03694
03695 for (i = 0; i < n_elements; ++i)
03696 {
03697 if (handle->caller_data[i].key == key)
03698 {
03699 stale = handle->caller_data[i].data;
03700 break;
03701 }
03702 }
03703
03704
03705
03706 if (i == n_elements)
03707 {
03708 lt_caller_data *temp
03709 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
03710
03711 if (!temp)
03712 {
03713 stale = 0;
03714 goto done;
03715 }
03716
03717 handle->caller_data = temp;
03718
03719
03720 handle->caller_data[i].key = key;
03721 handle->caller_data[1+ i].key = 0;
03722 }
03723
03724 handle->caller_data[i].data = data;
03725
03726 done:
03727 LT_DLMUTEX_UNLOCK ();
03728
03729 return stale;
03730 }
03731
03732 lt_ptr
03733 lt_dlcaller_get_data (key, handle)
03734 lt_dlcaller_id key;
03735 lt_dlhandle handle;
03736 {
03737 lt_ptr result = (lt_ptr) 0;
03738
03739
03740
03741 LT_DLMUTEX_LOCK ();
03742
03743
03744 {
03745 int i;
03746 for (i = 0; handle->caller_data[i].key; ++i)
03747 {
03748 if (handle->caller_data[i].key == key)
03749 {
03750 result = handle->caller_data[i].data;
03751 break;
03752 }
03753 }
03754 }
03755
03756 LT_DLMUTEX_UNLOCK ();
03757
03758 return result;
03759 }
03760
03761
03762
03763
03764
03765
03766 int
03767 lt_dlloader_add (place, dlloader, loader_name)
03768 lt_dlloader *place;
03769 const struct lt_user_dlloader *dlloader;
03770 const char *loader_name;
03771 {
03772 int errors = 0;
03773 lt_dlloader *node = 0, *ptr = 0;
03774
03775 if ((dlloader == 0)
03776 || (dlloader->module_open == 0)
03777 || (dlloader->module_close == 0)
03778 || (dlloader->find_sym == 0))
03779 {
03780 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
03781 return 1;
03782 }
03783
03784
03785 node = LT_EMALLOC (lt_dlloader, 1);
03786 if (!node)
03787 return 1;
03788
03789 node->next = 0;
03790 node->loader_name = loader_name;
03791 node->sym_prefix = dlloader->sym_prefix;
03792 node->dlloader_exit = dlloader->dlloader_exit;
03793 node->module_open = dlloader->module_open;
03794 node->module_close = dlloader->module_close;
03795 node->find_sym = dlloader->find_sym;
03796 node->dlloader_data = dlloader->dlloader_data;
03797
03798 LT_DLMUTEX_LOCK ();
03799 if (!loaders)
03800 {
03801
03802 loaders = node;
03803 }
03804 else if (!place)
03805 {
03806
03807
03808 for (ptr = loaders; ptr->next; ptr = ptr->next)
03809 {
03810 ;
03811 }
03812
03813 ptr->next = node;
03814 }
03815 else if (loaders == place)
03816 {
03817
03818 node->next = place;
03819 loaders = node;
03820 }
03821 else
03822 {
03823
03824 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
03825 {
03826 ;
03827 }
03828
03829 if (ptr->next != place)
03830 {
03831 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
03832 ++errors;
03833 }
03834 else
03835 {
03836
03837 node->next = place;
03838 ptr->next = node;
03839 }
03840 }
03841
03842 LT_DLMUTEX_UNLOCK ();
03843
03844 return errors;
03845 }
03846
03847 int
03848 lt_dlloader_remove (loader_name)
03849 const char *loader_name;
03850 {
03851 lt_dlloader *place = lt_dlloader_find (loader_name);
03852 lt_dlhandle handle;
03853 int errors = 0;
03854
03855 if (!place)
03856 {
03857 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
03858 return 1;
03859 }
03860
03861 LT_DLMUTEX_LOCK ();
03862
03863
03864 for (handle = handles; handle; handle = handle->next)
03865 {
03866 if (handle->loader == place)
03867 {
03868 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
03869 ++errors;
03870 goto done;
03871 }
03872 }
03873
03874 if (place == loaders)
03875 {
03876
03877 loaders = loaders->next;
03878 }
03879 else
03880 {
03881
03882 lt_dlloader *prev;
03883 for (prev = loaders; prev->next; prev = prev->next)
03884 {
03885 if (!strcmp (prev->next->loader_name, loader_name))
03886 {
03887 break;
03888 }
03889 }
03890
03891 place = prev->next;
03892 prev->next = prev->next->next;
03893 }
03894
03895 if (place->dlloader_exit)
03896 {
03897 errors = place->dlloader_exit (place->dlloader_data);
03898 }
03899
03900 LT_DLFREE (place);
03901
03902 done:
03903 LT_DLMUTEX_UNLOCK ();
03904
03905 return errors;
03906 }
03907
03908 lt_dlloader *
03909 lt_dlloader_next (place)
03910 lt_dlloader *place;
03911 {
03912 lt_dlloader *next;
03913
03914 LT_DLMUTEX_LOCK ();
03915 next = place ? place->next : loaders;
03916 LT_DLMUTEX_UNLOCK ();
03917
03918 return next;
03919 }
03920
03921 const char *
03922 lt_dlloader_name (place)
03923 lt_dlloader *place;
03924 {
03925 const char *name = 0;
03926
03927 if (place)
03928 {
03929 LT_DLMUTEX_LOCK ();
03930 name = place ? place->loader_name : 0;
03931 LT_DLMUTEX_UNLOCK ();
03932 }
03933 else
03934 {
03935 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
03936 }
03937
03938 return name;
03939 }
03940
03941 lt_user_data *
03942 lt_dlloader_data (place)
03943 lt_dlloader *place;
03944 {
03945 lt_user_data *data = 0;
03946
03947 if (place)
03948 {
03949 LT_DLMUTEX_LOCK ();
03950 data = place ? &(place->dlloader_data) : 0;
03951 LT_DLMUTEX_UNLOCK ();
03952 }
03953 else
03954 {
03955 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
03956 }
03957
03958 return data;
03959 }
03960
03961 lt_dlloader *
03962 lt_dlloader_find (loader_name)
03963 const char *loader_name;
03964 {
03965 lt_dlloader *place = 0;
03966
03967 LT_DLMUTEX_LOCK ();
03968 for (place = loaders; place; place = place->next)
03969 {
03970 if (strcmp (place->loader_name, loader_name) == 0)
03971 {
03972 break;
03973 }
03974 }
03975 LT_DLMUTEX_UNLOCK ();
03976
03977 return place;
03978 }