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