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