ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/libltdl/ltdl.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/libltdl/ltdl.c
File size: 55227 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

File Contents

# User Rev Content
1 michael 945 /* ltdl.c -- system independent dlopen wrapper
2    
3     Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
4 michael 1257 2007, 2008, 2011 Free Software Foundation, Inc.
5 michael 945 Written by Thomas Tanner, 1998
6    
7     NOTE: The canonical source of this file is maintained with the
8     GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9    
10     GNU Libltdl is free software; you can redistribute it and/or
11     modify it under the terms of the GNU Lesser General Public
12     License as published by the Free Software Foundation; either
13     version 2 of the License, or (at your option) any later version.
14    
15     As a special exception to the GNU Lesser General Public License,
16     if you distribute this file as part of a program or library that
17     is built using GNU Libtool, you may include this file under the
18     same distribution terms that you use for the rest of that program.
19    
20     GNU Libltdl is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23     GNU Lesser General Public License for more details.
24    
25     You should have received a copy of the GNU Lesser General Public
26     License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27     copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28     or obtained by writing to the Free Software Foundation, Inc.,
29     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30     */
31    
32     #include "lt__private.h"
33     #include "lt_system.h"
34     #include "lt_dlloader.h"
35    
36    
37     /* --- MANIFEST CONSTANTS --- */
38    
39    
40     /* Standard libltdl search path environment variable name */
41     #undef LTDL_SEARCHPATH_VAR
42     #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
43    
44     /* Standard libtool archive file extension. */
45     #undef LT_ARCHIVE_EXT
46     #define LT_ARCHIVE_EXT ".la"
47    
48     /* max. filename length */
49     #if !defined(LT_FILENAME_MAX)
50     # define LT_FILENAME_MAX 1024
51     #endif
52    
53     #if !defined(LT_LIBEXT)
54     # define LT_LIBEXT "a"
55     #endif
56    
57 michael 1107 #if !defined(LT_LIBPREFIX)
58     # define LT_LIBPREFIX "lib"
59     #endif
60    
61 michael 945 /* This is the maximum symbol size that won't require malloc/free */
62     #undef LT_SYMBOL_LENGTH
63     #define LT_SYMBOL_LENGTH 128
64    
65     /* This accounts for the _LTX_ separator */
66     #undef LT_SYMBOL_OVERHEAD
67     #define LT_SYMBOL_OVERHEAD 5
68    
69     /* Various boolean flags can be stored in the flags field of an
70     lt_dlhandle... */
71     #define LT_DLIS_RESIDENT(handle) ((handle)->info.is_resident)
72     #define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
73     #define LT_DLIS_SYMLOCAL(handle) ((handle)->info.is_symlocal)
74    
75    
76     static const char objdir[] = LT_OBJDIR;
77     static const char archive_ext[] = LT_ARCHIVE_EXT;
78     static const char libext[] = LT_LIBEXT;
79 michael 1107 static const char libprefix[] = LT_LIBPREFIX;
80 michael 945 #if defined(LT_MODULE_EXT)
81     static const char shlib_ext[] = LT_MODULE_EXT;
82     #endif
83 michael 1257 /* If the loadable module suffix is not the same as the linkable
84     * shared library suffix, this will be defined. */
85     #if defined(LT_SHARED_EXT)
86     static const char shared_ext[] = LT_SHARED_EXT;
87     #endif
88 michael 945 #if defined(LT_DLSEARCH_PATH)
89     static const char sys_dlsearch_path[] = LT_DLSEARCH_PATH;
90     #endif
91    
92    
93    
94    
95     /* --- DYNAMIC MODULE LOADING --- */
96    
97    
98     /* The type of a function used at each iteration of foreach_dirinpath(). */
99     typedef int foreach_callback_func (char *filename, void *data1,
100     void *data2);
101     /* foreachfile_callback itself calls a function of this type: */
102     typedef int file_worker_func (const char *filename, void *data);
103    
104    
105     static int foreach_dirinpath (const char *search_path,
106     const char *base_name,
107     foreach_callback_func *func,
108     void *data1, void *data2);
109     static int find_file_callback (char *filename, void *data1,
110     void *data2);
111     static int find_handle_callback (char *filename, void *data,
112     void *ignored);
113     static int foreachfile_callback (char *filename, void *data1,
114     void *data2);
115    
116    
117     static int canonicalize_path (const char *path, char **pcanonical);
118     static int argzize_path (const char *path,
119     char **pargz, size_t *pargz_len);
120     static FILE *find_file (const char *search_path,
121     const char *base_name, char **pdir);
122     static lt_dlhandle *find_handle (const char *search_path,
123     const char *base_name,
124     lt_dlhandle *handle,
125     lt_dladvise advise);
126     static int find_module (lt_dlhandle *handle, const char *dir,
127     const char *libdir, const char *dlname,
128     const char *old_name, int installed,
129     lt_dladvise advise);
130     static int has_library_ext (const char *filename);
131     static int load_deplibs (lt_dlhandle handle, char *deplibs);
132     static int trim (char **dest, const char *str);
133     static int try_dlopen (lt_dlhandle *handle,
134     const char *filename, const char *ext,
135     lt_dladvise advise);
136     static int tryall_dlopen (lt_dlhandle *handle,
137     const char *filename,
138     lt_dladvise padvise,
139     const lt_dlvtable *vtable);
140     static int unload_deplibs (lt_dlhandle handle);
141     static int lt_argz_insert (char **pargz, size_t *pargz_len,
142     char *before, const char *entry);
143     static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
144     const char *entry);
145     static int lt_argz_insertdir (char **pargz, size_t *pargz_len,
146     const char *dirnam, struct dirent *dp);
147     static int lt_dlpath_insertdir (char **ppath, char *before,
148     const char *dir);
149     static int list_files_by_dir (const char *dirnam,
150     char **pargz, size_t *pargz_len);
151     static int file_not_found (void);
152    
153     #ifdef HAVE_LIBDLLOADER
154     static int loader_init_callback (lt_dlhandle handle);
155     #endif /* HAVE_LIBDLLOADER */
156    
157     static int loader_init (lt_get_vtable *vtable_func,
158     lt_user_data data);
159    
160     static char *user_search_path= 0;
161     static lt_dlhandle handles = 0;
162     static int initialized = 0;
163    
164     /* Our memory failure callback sets the error message to be passed back
165     up to the client, so we must be careful to return from mallocation
166     callers if allocation fails (as this callback returns!!). */
167     void
168     lt__alloc_die_callback (void)
169     {
170     LT__SETERROR (NO_MEMORY);
171     }
172    
173     #ifdef HAVE_LIBDLLOADER
174     /* This function is called to initialise each preloaded module loader,
175     and hook it into the list of loaders to be used when attempting to
176     dlopen an application module. */
177     static int
178     loader_init_callback (lt_dlhandle handle)
179     {
180     lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
181     return loader_init (vtable_func, 0);
182     }
183     #endif /* HAVE_LIBDLLOADER */
184    
185     static int
186     loader_init (lt_get_vtable *vtable_func, lt_user_data data)
187     {
188     const lt_dlvtable *vtable = 0;
189     int errors = 0;
190    
191     if (vtable_func)
192     {
193     vtable = (*vtable_func) (data);
194     }
195    
196     /* lt_dlloader_add will LT__SETERROR if it fails. */
197     errors += lt_dlloader_add (vtable);
198    
199     assert (errors || vtable);
200    
201     if ((!errors) && vtable->dlloader_init)
202     {
203     if ((*vtable->dlloader_init) (vtable->dlloader_data))
204     {
205     LT__SETERROR (INIT_LOADER);
206     ++errors;
207     }
208     }
209    
210     return errors;
211     }
212    
213     /* Bootstrap the loader loading with the preopening loader. */
214     #define get_vtable preopen_LTX_get_vtable
215     #define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
216    
217     LT_BEGIN_C_DECLS
218     LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data);
219     LT_END_C_DECLS
220     #ifdef HAVE_LIBDLLOADER
221 michael 1107 extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
222 michael 945 #endif
223    
224     /* Initialize libltdl. */
225     int
226     lt_dlinit (void)
227     {
228     int errors = 0;
229    
230     /* Initialize only at first call. */
231     if (++initialized == 1)
232     {
233     lt__alloc_die = lt__alloc_die_callback;
234     handles = 0;
235     user_search_path = 0; /* empty search path */
236    
237     /* First set up the statically loaded preload module loader, so
238     we can use it to preopen the other loaders we linked in at
239     compile time. */
240     errors += loader_init (get_vtable, 0);
241    
242     /* Now open all the preloaded module loaders, so the application
243     can use _them_ to lt_dlopen its own modules. */
244     #ifdef HAVE_LIBDLLOADER
245     if (!errors)
246     {
247 michael 1094 errors += lt_dlpreload (preloaded_symbols);
248 michael 945 }
249    
250     if (!errors)
251     {
252     errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
253     }
254     #endif /* HAVE_LIBDLLOADER */
255     }
256    
257     #ifdef LT_DEBUG_LOADERS
258     lt_dlloader_dump();
259     #endif
260    
261     return errors;
262     }
263    
264     int
265     lt_dlexit (void)
266     {
267     /* shut down libltdl */
268     lt_dlloader *loader = 0;
269     lt_dlhandle handle = handles;
270     int errors = 0;
271    
272     if (!initialized)
273     {
274     LT__SETERROR (SHUTDOWN);
275     ++errors;
276     goto done;
277     }
278    
279     /* shut down only at last call. */
280     if (--initialized == 0)
281     {
282     int level;
283    
284     while (handles && LT_DLIS_RESIDENT (handles))
285     {
286     handles = handles->next;
287     }
288    
289     /* close all modules */
290     for (level = 1; handle; ++level)
291     {
292     lt_dlhandle cur = handles;
293     int saw_nonresident = 0;
294    
295     while (cur)
296     {
297     lt_dlhandle tmp = cur;
298     cur = cur->next;
299     if (!LT_DLIS_RESIDENT (tmp))
300     {
301     saw_nonresident = 1;
302     if (tmp->info.ref_count <= level)
303     {
304     if (lt_dlclose (tmp))
305     {
306     ++errors;
307     }
308     /* Make sure that the handle pointed to by 'cur' still exists.
309     lt_dlclose recursively closes dependent libraries which removes
310     them from the linked list. One of these might be the one
311     pointed to by 'cur'. */
312     if (cur)
313     {
314     for (tmp = handles; tmp; tmp = tmp->next)
315     if (tmp == cur)
316     break;
317     if (! tmp)
318     cur = handles;
319     }
320     }
321     }
322     }
323     /* done if only resident modules are left */
324     if (!saw_nonresident)
325     break;
326     }
327    
328     /* When removing loaders, we can only find out failure by testing
329     the error string, so avoid a spurious one from an earlier
330     failed command. */
331     if (!errors)
332     LT__SETERRORSTR (0);
333    
334     /* close all loaders */
335     for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
336     {
337     lt_dlloader *next = (lt_dlloader *) lt_dlloader_next (loader);
338     lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
339    
340     if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
341     {
342     FREE (vtable);
343     }
344     else
345     {
346     /* ignore errors due to resident modules */
347     const char *err;
348     LT__GETERROR (err);
349     if (err)
350     ++errors;
351     }
352    
353     loader = next;
354     }
355    
356     FREE(user_search_path);
357     }
358    
359     done:
360     return errors;
361     }
362    
363    
364     /* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
365     If the library is not successfully loaded, return non-zero. Otherwise,
366     the dlhandle is stored at the address given in PHANDLE. */
367     static int
368     tryall_dlopen (lt_dlhandle *phandle, const char *filename,
369     lt_dladvise advise, const lt_dlvtable *vtable)
370     {
371     lt_dlhandle handle = handles;
372     const char * saved_error = 0;
373     int errors = 0;
374    
375     #ifdef LT_DEBUG_LOADERS
376     fprintf (stderr, "tryall_dlopen (%s, %s)\n",
377     filename ? filename : "(null)",
378     vtable ? vtable->name : "(ALL)");
379     #endif
380    
381     LT__GETERROR (saved_error);
382    
383     /* check whether the module was already opened */
384     for (;handle; handle = handle->next)
385     {
386     if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
387     || (handle->info.filename && filename
388     && streq (handle->info.filename, filename)))
389     {
390     break;
391     }
392     }
393    
394     if (handle)
395     {
396     ++handle->info.ref_count;
397     *phandle = handle;
398     goto done;
399     }
400    
401     handle = *phandle;
402     if (filename)
403     {
404     /* Comment out the check of file permissions using access.
405     This call seems to always return -1 with error EACCES.
406     */
407     /* We need to catch missing file errors early so that
408     file_not_found() can detect what happened.
409     if (access (filename, R_OK) != 0)
410     {
411     LT__SETERROR (FILE_NOT_FOUND);
412     ++errors;
413     goto done;
414     } */
415    
416     handle->info.filename = lt__strdup (filename);
417     if (!handle->info.filename)
418     {
419     ++errors;
420     goto done;
421     }
422     }
423     else
424     {
425     handle->info.filename = 0;
426     }
427    
428     {
429     lt_dlloader loader = lt_dlloader_next (0);
430     const lt_dlvtable *loader_vtable;
431    
432     do
433     {
434     if (vtable)
435     loader_vtable = vtable;
436     else
437     loader_vtable = lt_dlloader_get (loader);
438    
439     #ifdef LT_DEBUG_LOADERS
440     fprintf (stderr, "Calling %s->module_open (%s)\n",
441     (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
442     filename ? filename : "(null)");
443     #endif
444     handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
445     filename, advise);
446     #ifdef LT_DEBUG_LOADERS
447     fprintf (stderr, " Result: %s\n",
448     handle->module ? "Success" : "Failed");
449     #endif
450    
451     if (handle->module != 0)
452     {
453     if (advise)
454     {
455     handle->info.is_resident = advise->is_resident;
456     handle->info.is_symglobal = advise->is_symglobal;
457     handle->info.is_symlocal = advise->is_symlocal;
458     }
459     break;
460     }
461     }
462     while (!vtable && (loader = lt_dlloader_next (loader)));
463    
464     /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
465     given but we exhausted all loaders without opening the module, bail
466     out! */
467     if ((vtable && !handle->module)
468     || (!vtable && !loader))
469     {
470     FREE (handle->info.filename);
471     ++errors;
472     goto done;
473     }
474    
475     handle->vtable = loader_vtable;
476     }
477    
478     LT__SETERRORSTR (saved_error);
479    
480     done:
481     return errors;
482     }
483    
484    
485     static int
486     tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
487     const char *dirname, const char *dlname,
488     lt_dladvise advise)
489     {
490     int error = 0;
491     char *filename = 0;
492     size_t filename_len = 0;
493     size_t dirname_len = LT_STRLEN (dirname);
494    
495     assert (handle);
496     assert (dirname);
497     assert (dlname);
498     #if defined(LT_DIRSEP_CHAR)
499     /* Only canonicalized names (i.e. with DIRSEP chars already converted)
500     should make it into this function: */
501     assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
502     #endif
503    
504     if (dirname_len > 0)
505     if (dirname[dirname_len -1] == '/')
506     --dirname_len;
507     filename_len = dirname_len + 1 + LT_STRLEN (dlname);
508    
509     /* Allocate memory, and combine DIRNAME and MODULENAME into it.
510     The PREFIX (if any) is handled below. */
511     filename = MALLOC (char, filename_len + 1);
512     if (!filename)
513     return 1;
514    
515     sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
516    
517     /* Now that we have combined DIRNAME and MODULENAME, if there is
518     also a PREFIX to contend with, simply recurse with the arguments
519     shuffled. Otherwise, attempt to open FILENAME as a module. */
520     if (prefix)
521     {
522     error += tryall_dlopen_module (handle, (const char *) 0,
523     prefix, filename, advise);
524     }
525     else if (tryall_dlopen (handle, filename, advise, 0) != 0)
526     {
527     ++error;
528     }
529    
530     FREE (filename);
531     return error;
532     }
533    
534     static int
535     find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
536     const char *dlname, const char *old_name, int installed,
537     lt_dladvise advise)
538     {
539     /* Try to open the old library first; if it was dlpreopened,
540     we want the preopened version of it, even if a dlopenable
541     module is available. */
542 michael 1037 if (old_name && tryall_dlopen (handle, old_name,
543     advise, lt_dlloader_find ("lt_preopen") ) == 0)
544 michael 945 {
545     return 0;
546     }
547    
548     /* Try to open the dynamic library. */
549     if (dlname)
550     {
551     /* try to open the installed module */
552     if (installed && libdir)
553     {
554     if (tryall_dlopen_module (handle, (const char *) 0,
555     libdir, dlname, advise) == 0)
556     return 0;
557     }
558    
559     /* try to open the not-installed module */
560     if (!installed)
561     {
562     if (tryall_dlopen_module (handle, dir, objdir,
563     dlname, advise) == 0)
564     return 0;
565     }
566    
567     /* maybe it was moved to another directory */
568     {
569     if (dir && (tryall_dlopen_module (handle, (const char *) 0,
570     dir, dlname, advise) == 0))
571     return 0;
572     }
573     }
574    
575     return 1;
576     }
577    
578    
579     static int
580     canonicalize_path (const char *path, char **pcanonical)
581     {
582     char *canonical = 0;
583    
584     assert (path && *path);
585     assert (pcanonical);
586    
587     canonical = MALLOC (char, 1+ LT_STRLEN (path));
588     if (!canonical)
589     return 1;
590    
591     {
592     size_t dest = 0;
593     size_t src;
594     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
595     {
596     /* Path separators are not copied to the beginning or end of
597     the destination, or if another separator would follow
598     immediately. */
599     if (path[src] == LT_PATHSEP_CHAR)
600     {
601     if ((dest == 0)
602     || (path[1+ src] == LT_PATHSEP_CHAR)
603     || (path[1+ src] == LT_EOS_CHAR))
604     continue;
605     }
606    
607     /* Anything other than a directory separator is copied verbatim. */
608     if ((path[src] != '/')
609     #if defined(LT_DIRSEP_CHAR)
610     && (path[src] != LT_DIRSEP_CHAR)
611     #endif
612     )
613     {
614     canonical[dest++] = path[src];
615     }
616     /* Directory separators are converted and copied only if they are
617     not at the end of a path -- i.e. before a path separator or
618     NULL terminator. */
619     else if ((path[1+ src] != LT_PATHSEP_CHAR)
620     && (path[1+ src] != LT_EOS_CHAR)
621     #if defined(LT_DIRSEP_CHAR)
622     && (path[1+ src] != LT_DIRSEP_CHAR)
623     #endif
624     && (path[1+ src] != '/'))
625     {
626     canonical[dest++] = '/';
627     }
628     }
629    
630     /* Add an end-of-string marker at the end. */
631     canonical[dest] = LT_EOS_CHAR;
632     }
633    
634     /* Assign new value. */
635     *pcanonical = canonical;
636    
637     return 0;
638     }
639    
640     static int
641     argzize_path (const char *path, char **pargz, size_t *pargz_len)
642     {
643     error_t error;
644    
645     assert (path);
646     assert (pargz);
647     assert (pargz_len);
648    
649     if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
650     {
651     switch (error)
652     {
653     case ENOMEM:
654     LT__SETERROR (NO_MEMORY);
655     break;
656     default:
657     LT__SETERROR (UNKNOWN);
658     break;
659     }
660    
661     return 1;
662     }
663    
664     return 0;
665     }
666    
667     /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
668     of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
669     non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
670     it is appended to each SEARCH_PATH element before FUNC is called. */
671     static int
672     foreach_dirinpath (const char *search_path, const char *base_name,
673     foreach_callback_func *func, void *data1, void *data2)
674     {
675     int result = 0;
676     size_t filenamesize = 0;
677     size_t lenbase = LT_STRLEN (base_name);
678     size_t argz_len = 0;
679     char *argz = 0;
680     char *filename = 0;
681     char *canonical = 0;
682    
683     if (!search_path || !*search_path)
684     {
685     LT__SETERROR (FILE_NOT_FOUND);
686     goto cleanup;
687     }
688    
689     if (canonicalize_path (search_path, &canonical) != 0)
690     goto cleanup;
691    
692     if (argzize_path (canonical, &argz, &argz_len) != 0)
693     goto cleanup;
694    
695     {
696     char *dir_name = 0;
697     while ((dir_name = argz_next (argz, argz_len, dir_name)))
698     {
699     size_t lendir = LT_STRLEN (dir_name);
700    
701     if (1+ lendir + lenbase >= filenamesize)
702     {
703     FREE (filename);
704     filenamesize = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
705     filename = MALLOC (char, filenamesize);
706     if (!filename)
707     goto cleanup;
708     }
709    
710     assert (filenamesize > lendir);
711     strcpy (filename, dir_name);
712    
713     if (base_name && *base_name)
714     {
715     if (filename[lendir -1] != '/')
716     filename[lendir++] = '/';
717     strcpy (filename +lendir, base_name);
718     }
719    
720     if ((result = (*func) (filename, data1, data2)))
721     {
722     break;
723     }
724     }
725     }
726    
727     cleanup:
728     FREE (argz);
729     FREE (canonical);
730     FREE (filename);
731    
732     return result;
733     }
734    
735     /* If FILEPATH can be opened, store the name of the directory component
736     in DATA1, and the opened FILE* structure address in DATA2. Otherwise
737     DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
738     static int
739     find_file_callback (char *filename, void *data1, void *data2)
740     {
741     char **pdir = (char **) data1;
742     FILE **pfile = (FILE **) data2;
743     int is_done = 0;
744    
745     assert (filename && *filename);
746     assert (pdir);
747     assert (pfile);
748    
749     if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
750     {
751     char *dirend = strrchr (filename, '/');
752    
753     if (dirend > filename)
754     *dirend = LT_EOS_CHAR;
755    
756     FREE (*pdir);
757     *pdir = lt__strdup (filename);
758     is_done = (*pdir == 0) ? -1 : 1;
759     }
760    
761     return is_done;
762     }
763    
764     static FILE *
765     find_file (const char *search_path, const char *base_name, char **pdir)
766     {
767     FILE *file = 0;
768    
769     foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
770    
771     return file;
772     }
773    
774     static int
775     find_handle_callback (char *filename, void *data, void *data2)
776     {
777     lt_dlhandle *phandle = (lt_dlhandle *) data;
778     int notfound = access (filename, R_OK);
779     lt_dladvise advise = (lt_dladvise) data2;
780    
781     /* Bail out if file cannot be read... */
782     if (notfound)
783     return 0;
784    
785     /* Try to dlopen the file, but do not continue searching in any
786     case. */
787     if (tryall_dlopen (phandle, filename, advise, 0) != 0)
788     *phandle = 0;
789    
790     return 1;
791     }
792    
793     /* If HANDLE was found return it, otherwise return 0. If HANDLE was
794     found but could not be opened, *HANDLE will be set to 0. */
795     static lt_dlhandle *
796     find_handle (const char *search_path, const char *base_name,
797     lt_dlhandle *phandle, lt_dladvise advise)
798     {
799     if (!search_path)
800     return 0;
801    
802     if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
803     phandle, advise))
804     return 0;
805    
806     return phandle;
807     }
808    
809     #if !defined(LTDL_DLOPEN_DEPLIBS)
810     static int
811     load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
812     {
813     handle->depcount = 0;
814     return 0;
815     }
816    
817     #else /* defined(LTDL_DLOPEN_DEPLIBS) */
818     static int
819     load_deplibs (lt_dlhandle handle, char *deplibs)
820     {
821     char *p, *save_search_path = 0;
822     int depcount = 0;
823     int i;
824     char **names = 0;
825     int errors = 0;
826    
827     handle->depcount = 0;
828    
829     if (!deplibs)
830     {
831     return errors;
832     }
833     ++errors;
834    
835     if (user_search_path)
836     {
837     save_search_path = lt__strdup (user_search_path);
838     if (!save_search_path)
839     goto cleanup;
840     }
841    
842     /* extract search paths and count deplibs */
843     p = deplibs;
844     while (*p)
845     {
846     if (!isspace ((unsigned char) *p))
847     {
848     char *end = p+1;
849     while (*end && !isspace((unsigned char) *end))
850     {
851     ++end;
852     }
853    
854     if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
855     {
856     char save = *end;
857     *end = 0; /* set a temporary string terminator */
858     if (lt_dladdsearchdir(p+2))
859     {
860     goto cleanup;
861     }
862     *end = save;
863     }
864     else
865     {
866     ++depcount;
867     }
868    
869     p = end;
870     }
871     else
872     {
873     ++p;
874     }
875     }
876    
877    
878     if (!depcount)
879     {
880     errors = 0;
881     goto cleanup;
882     }
883    
884     names = MALLOC (char *, depcount);
885     if (!names)
886     goto cleanup;
887    
888     /* now only extract the actual deplibs */
889     depcount = 0;
890     p = deplibs;
891     while (*p)
892     {
893     if (isspace ((unsigned char) *p))
894     {
895     ++p;
896     }
897     else
898     {
899     char *end = p+1;
900     while (*end && !isspace ((unsigned char) *end))
901     {
902     ++end;
903     }
904    
905     if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
906     {
907     char *name;
908     char save = *end;
909     *end = 0; /* set a temporary string terminator */
910     if (strncmp(p, "-l", 2) == 0)
911     {
912     size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
913     name = MALLOC (char, 1+ name_len);
914     if (name)
915     sprintf (name, "lib%s", p+2);
916     }
917     else
918     name = lt__strdup(p);
919    
920     if (!name)
921     goto cleanup_names;
922    
923     names[depcount++] = name;
924     *end = save;
925     }
926     p = end;
927     }
928     }
929    
930     /* load the deplibs (in reverse order)
931     At this stage, don't worry if the deplibs do not load correctly,
932     they may already be statically linked into the loading application
933     for instance. There will be a more enlightening error message
934     later on if the loaded module cannot resolve all of its symbols. */
935     if (depcount)
936     {
937     lt_dlhandle cur = handle;
938     int j = 0;
939    
940     cur->deplibs = MALLOC (lt_dlhandle, depcount);
941     if (!cur->deplibs)
942     goto cleanup_names;
943    
944     for (i = 0; i < depcount; ++i)
945     {
946     cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
947     if (cur->deplibs[j])
948     {
949     ++j;
950     }
951     }
952    
953     cur->depcount = j; /* Number of successfully loaded deplibs */
954     errors = 0;
955     }
956    
957     cleanup_names:
958     for (i = 0; i < depcount; ++i)
959     {
960     FREE (names[i]);
961     }
962    
963     cleanup:
964     FREE (names);
965     /* restore the old search path */
966     if (save_search_path) {
967     MEMREASSIGN (user_search_path, save_search_path);
968     }
969    
970     return errors;
971     }
972     #endif /* defined(LTDL_DLOPEN_DEPLIBS) */
973    
974     static int
975     unload_deplibs (lt_dlhandle handle)
976     {
977     int i;
978     int errors = 0;
979     lt_dlhandle cur = handle;
980    
981     if (cur->depcount)
982     {
983     for (i = 0; i < cur->depcount; ++i)
984     {
985     if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
986     {
987     errors += lt_dlclose (cur->deplibs[i]);
988     }
989     }
990     FREE (cur->deplibs);
991     }
992    
993     return errors;
994     }
995    
996     static int
997     trim (char **dest, const char *str)
998     {
999     /* remove the leading and trailing "'" from str
1000     and store the result in dest */
1001     const char *end = strrchr (str, '\'');
1002     size_t len = LT_STRLEN (str);
1003     char *tmp;
1004    
1005     FREE (*dest);
1006    
1007 michael 1094 if (!end || end == str)
1008 michael 945 return 1;
1009    
1010     if (len > 3 && str[0] == '\'')
1011     {
1012     tmp = MALLOC (char, end - str);
1013     if (!tmp)
1014     return 1;
1015    
1016     memcpy(tmp, &str[1], (end - str) - 1);
1017     tmp[(end - str) - 1] = LT_EOS_CHAR;
1018     *dest = tmp;
1019     }
1020     else
1021     {
1022     *dest = 0;
1023     }
1024    
1025     return 0;
1026     }
1027    
1028     /* Read the .la file FILE. */
1029     static int
1030     parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1031     char **old_name, int *installed)
1032     {
1033     int errors = 0;
1034     size_t line_len = LT_FILENAME_MAX;
1035     char * line = MALLOC (char, line_len);
1036    
1037     if (!line)
1038     {
1039     LT__SETERROR (FILE_NOT_FOUND);
1040     return 1;
1041     }
1042    
1043     while (!feof (file))
1044     {
1045     line[line_len-2] = '\0';
1046     if (!fgets (line, (int) line_len, file))
1047     {
1048     break;
1049     }
1050    
1051     /* Handle the case where we occasionally need to read a line
1052     that is longer than the initial buffer size.
1053     Behave even if the file contains NUL bytes due to corruption. */
1054     while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
1055     {
1056     line = REALLOC (char, line, line_len *2);
1057     if (!line)
1058     {
1059     ++errors;
1060     goto cleanup;
1061     }
1062     line[line_len * 2 - 2] = '\0';
1063     if (!fgets (&line[line_len -1], (int) line_len +1, file))
1064     {
1065     break;
1066     }
1067     line_len *= 2;
1068     }
1069    
1070     if (line[0] == '\n' || line[0] == '#')
1071     {
1072     continue;
1073     }
1074    
1075     #undef STR_DLNAME
1076     #define STR_DLNAME "dlname="
1077     if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
1078     {
1079     errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
1080     }
1081    
1082     #undef STR_OLD_LIBRARY
1083     #define STR_OLD_LIBRARY "old_library="
1084     else if (strncmp (line, STR_OLD_LIBRARY,
1085     sizeof (STR_OLD_LIBRARY) - 1) == 0)
1086     {
1087     errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
1088     }
1089 michael 1094
1090     /* Windows native tools do not understand the POSIX paths we store
1091     in libdir. */
1092 michael 945 #undef STR_LIBDIR
1093     #define STR_LIBDIR "libdir="
1094     else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
1095     {
1096     errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
1097 michael 1107 #ifdef __WINDOWS__
1098     /* Disallow following unix-style paths on MinGW. */
1099     if (*libdir && (**libdir == '/' || **libdir == '\\'))
1100     **libdir = '\0';
1101     #endif
1102 michael 945 }
1103    
1104     #undef STR_DL_DEPLIBS
1105     #define STR_DL_DEPLIBS "dependency_libs="
1106     else if (strncmp (line, STR_DL_DEPLIBS,
1107     sizeof (STR_DL_DEPLIBS) - 1) == 0)
1108     {
1109     errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
1110     }
1111     else if (streq (line, "installed=yes\n"))
1112     {
1113     *installed = 1;
1114     }
1115     else if (streq (line, "installed=no\n"))
1116     {
1117     *installed = 0;
1118     }
1119    
1120     #undef STR_LIBRARY_NAMES
1121     #define STR_LIBRARY_NAMES "library_names="
1122     else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
1123     sizeof (STR_LIBRARY_NAMES) - 1) == 0)
1124     {
1125     char *last_libname;
1126     errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
1127     if (!errors
1128     && *dlname
1129     && (last_libname = strrchr (*dlname, ' ')) != 0)
1130     {
1131     last_libname = lt__strdup (last_libname + 1);
1132     if (!last_libname)
1133     {
1134     ++errors;
1135     goto cleanup;
1136     }
1137     MEMREASSIGN (*dlname, last_libname);
1138     }
1139     }
1140    
1141     if (errors)
1142     break;
1143     }
1144     cleanup:
1145     FREE (line);
1146     return errors;
1147     }
1148    
1149    
1150     /* Try to open FILENAME as a module. */
1151     static int
1152     try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1153     lt_dladvise advise)
1154     {
1155     const char * saved_error = 0;
1156     char * archive_name = 0;
1157     char * canonical = 0;
1158     char * base_name = 0;
1159     char * dir = 0;
1160     char * name = 0;
1161     char * attempt = 0;
1162     int errors = 0;
1163     lt_dlhandle newhandle;
1164    
1165     assert (phandle);
1166     assert (*phandle == 0);
1167    
1168     #ifdef LT_DEBUG_LOADERS
1169     fprintf (stderr, "try_dlopen (%s, %s)\n",
1170     filename ? filename : "(null)",
1171     ext ? ext : "(null)");
1172     #endif
1173    
1174     LT__GETERROR (saved_error);
1175    
1176     /* dlopen self? */
1177     if (!filename)
1178     {
1179     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1180     if (*phandle == 0)
1181     return 1;
1182    
1183     newhandle = *phandle;
1184    
1185     /* lt_dlclose()ing yourself is very bad! Disallow it. */
1186     newhandle->info.is_resident = 1;
1187    
1188     if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1189     {
1190     FREE (*phandle);
1191     return 1;
1192     }
1193    
1194     goto register_handle;
1195     }
1196    
1197     assert (filename && *filename);
1198    
1199     if (ext)
1200     {
1201     attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
1202     if (!attempt)
1203     return 1;
1204    
1205     sprintf(attempt, "%s%s", filename, ext);
1206     }
1207     else
1208     {
1209     attempt = lt__strdup (filename);
1210     if (!attempt)
1211     return 1;
1212     }
1213    
1214     /* Doing this immediately allows internal functions to safely
1215     assume only canonicalized paths are passed. */
1216     if (canonicalize_path (attempt, &canonical) != 0)
1217     {
1218     ++errors;
1219     goto cleanup;
1220     }
1221    
1222     /* If the canonical module name is a path (relative or absolute)
1223     then split it into a directory part and a name part. */
1224     base_name = strrchr (canonical, '/');
1225     if (base_name)
1226     {
1227     size_t dirlen = (1+ base_name) - canonical;
1228    
1229     dir = MALLOC (char, 1+ dirlen);
1230     if (!dir)
1231     {
1232     ++errors;
1233     goto cleanup;
1234     }
1235    
1236     strncpy (dir, canonical, dirlen);
1237     dir[dirlen] = LT_EOS_CHAR;
1238    
1239     ++base_name;
1240     }
1241     else
1242     MEMREASSIGN (base_name, canonical);
1243    
1244     assert (base_name && *base_name);
1245    
1246     ext = strrchr (base_name, '.');
1247     if (!ext)
1248     {
1249     ext = base_name + LT_STRLEN (base_name);
1250     }
1251    
1252     /* extract the module name from the file name */
1253     name = MALLOC (char, ext - base_name + 1);
1254     if (!name)
1255     {
1256     ++errors;
1257     goto cleanup;
1258     }
1259    
1260     /* canonicalize the module name */
1261     {
1262     int i;
1263     for (i = 0; i < ext - base_name; ++i)
1264     {
1265     if (isalnum ((unsigned char)(base_name[i])))
1266     {
1267     name[i] = base_name[i];
1268     }
1269     else
1270     {
1271     name[i] = '_';
1272     }
1273     }
1274     name[ext - base_name] = LT_EOS_CHAR;
1275     }
1276    
1277     /* Before trawling through the filesystem in search of a module,
1278     check whether we are opening a preloaded module. */
1279     if (!dir)
1280     {
1281     const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1282    
1283     if (vtable)
1284     {
1285 michael 1107 /* libprefix + name + "." + libext + NULL */
1286     archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
1287 michael 945 *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1288    
1289     if ((*phandle == NULL) || (archive_name == NULL))
1290     {
1291     ++errors;
1292     goto cleanup;
1293     }
1294     newhandle = *phandle;
1295    
1296     /* Preloaded modules are always named according to their old
1297     archive name. */
1298 michael 1107 if (strncmp(name, "lib", 3) == 0)
1299     {
1300     sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
1301     }
1302     else
1303     {
1304     sprintf (archive_name, "%s.%s", name, libext);
1305     }
1306 michael 945
1307     if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
1308     {
1309     goto register_handle;
1310     }
1311    
1312     /* If we're still here, there was no matching preloaded module,
1313     so put things back as we found them, and continue searching. */
1314     FREE (*phandle);
1315     newhandle = NULL;
1316     }
1317     }
1318    
1319     /* If we are allowing only preloaded modules, and we didn't find
1320     anything yet, give up on the search here. */
1321     if (advise && advise->try_preload_only)
1322     {
1323     goto cleanup;
1324     }
1325    
1326     /* Check whether we are opening a libtool module (.la extension). */
1327     if (ext && streq (ext, archive_ext))
1328     {
1329     /* this seems to be a libtool module */
1330     FILE * file = 0;
1331     char * dlname = 0;
1332     char * old_name = 0;
1333     char * libdir = 0;
1334     char * deplibs = 0;
1335    
1336     /* if we can't find the installed flag, it is probably an
1337     installed libtool archive, produced with an old version
1338     of libtool */
1339     int installed = 1;
1340    
1341     /* Now try to open the .la file. If there is no directory name
1342     component, try to find it first in user_search_path and then other
1343     prescribed paths. Otherwise (or in any case if the module was not
1344     yet found) try opening just the module name as passed. */
1345     if (!dir)
1346     {
1347     const char *search_path = user_search_path;
1348    
1349     if (search_path)
1350     file = find_file (user_search_path, base_name, &dir);
1351    
1352     if (!file)
1353     {
1354     search_path = getenv (LTDL_SEARCHPATH_VAR);
1355     if (search_path)
1356     file = find_file (search_path, base_name, &dir);
1357     }
1358    
1359     #if defined(LT_MODULE_PATH_VAR)
1360     if (!file)
1361     {
1362     search_path = getenv (LT_MODULE_PATH_VAR);
1363     if (search_path)
1364     file = find_file (search_path, base_name, &dir);
1365     }
1366     #endif
1367     #if defined(LT_DLSEARCH_PATH)
1368     if (!file && *sys_dlsearch_path)
1369     {
1370     file = find_file (sys_dlsearch_path, base_name, &dir);
1371     }
1372     #endif
1373     }
1374 michael 1037 else
1375 michael 945 {
1376     file = fopen (attempt, LT_READTEXT_MODE);
1377     }
1378    
1379     /* If we didn't find the file by now, it really isn't there. Set
1380     the status flag, and bail out. */
1381     if (!file)
1382     {
1383     LT__SETERROR (FILE_NOT_FOUND);
1384     ++errors;
1385     goto cleanup;
1386     }
1387    
1388     /* read the .la file */
1389     if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1390     &old_name, &installed) != 0)
1391     ++errors;
1392    
1393     fclose (file);
1394    
1395     /* allocate the handle */
1396     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1397     if (*phandle == 0)
1398     ++errors;
1399    
1400     if (errors)
1401     {
1402     FREE (dlname);
1403     FREE (old_name);
1404     FREE (libdir);
1405     FREE (deplibs);
1406     FREE (*phandle);
1407     goto cleanup;
1408     }
1409    
1410     assert (*phandle);
1411    
1412     if (load_deplibs (*phandle, deplibs) == 0)
1413     {
1414     newhandle = *phandle;
1415     /* find_module may replace newhandle */
1416     if (find_module (&newhandle, dir, libdir, dlname, old_name,
1417     installed, advise))
1418     {
1419     unload_deplibs (*phandle);
1420     ++errors;
1421     }
1422     }
1423     else
1424     {
1425     ++errors;
1426     }
1427    
1428     FREE (dlname);
1429     FREE (old_name);
1430     FREE (libdir);
1431     FREE (deplibs);
1432    
1433     if (errors)
1434     {
1435     FREE (*phandle);
1436     goto cleanup;
1437     }
1438    
1439     if (*phandle != newhandle)
1440     {
1441     unload_deplibs (*phandle);
1442     }
1443     }
1444     else
1445     {
1446     /* not a libtool module */
1447     *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1448     if (*phandle == 0)
1449     {
1450     ++errors;
1451     goto cleanup;
1452     }
1453    
1454     newhandle = *phandle;
1455    
1456     /* If the module has no directory name component, try to find it
1457     first in user_search_path and then other prescribed paths.
1458     Otherwise (or in any case if the module was not yet found) try
1459     opening just the module name as passed. */
1460     if ((dir || (!find_handle (user_search_path, base_name,
1461     &newhandle, advise)
1462     && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1463     &newhandle, advise)
1464     #if defined(LT_MODULE_PATH_VAR)
1465     && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1466     &newhandle, advise)
1467     #endif
1468     #if defined(LT_DLSEARCH_PATH)
1469     && !find_handle (sys_dlsearch_path, base_name,
1470     &newhandle, advise)
1471     #endif
1472     )))
1473     {
1474     if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1475     {
1476     newhandle = NULL;
1477     }
1478     }
1479    
1480     if (!newhandle)
1481     {
1482     FREE (*phandle);
1483     ++errors;
1484     goto cleanup;
1485     }
1486     }
1487    
1488     register_handle:
1489     MEMREASSIGN (*phandle, newhandle);
1490    
1491     if ((*phandle)->info.ref_count == 0)
1492     {
1493     (*phandle)->info.ref_count = 1;
1494     MEMREASSIGN ((*phandle)->info.name, name);
1495    
1496     (*phandle)->next = handles;
1497     handles = *phandle;
1498     }
1499    
1500     LT__SETERRORSTR (saved_error);
1501    
1502     cleanup:
1503     FREE (dir);
1504     FREE (attempt);
1505     FREE (name);
1506     if (!canonical) /* was MEMREASSIGNed */
1507     FREE (base_name);
1508     FREE (canonical);
1509     FREE (archive_name);
1510    
1511     return errors;
1512     }
1513    
1514    
1515 michael 1094 /* If the last error message stored was `FILE_NOT_FOUND', then return
1516 michael 945 non-zero. */
1517     static int
1518     file_not_found (void)
1519     {
1520     const char *error = 0;
1521    
1522     LT__GETERROR (error);
1523     if (error == LT__STRERROR (FILE_NOT_FOUND))
1524     return 1;
1525    
1526     return 0;
1527     }
1528    
1529    
1530     /* Unless FILENAME already bears a suitable library extension, then
1531     return 0. */
1532     static int
1533     has_library_ext (const char *filename)
1534     {
1535 michael 1094 const char * ext = 0;
1536 michael 945
1537     assert (filename);
1538    
1539     ext = strrchr (filename, '.');
1540    
1541     if (ext && ((streq (ext, archive_ext))
1542     #if defined(LT_MODULE_EXT)
1543     || (streq (ext, shlib_ext))
1544     #endif
1545 michael 1257 #if defined(LT_SHARED_EXT)
1546     || (streq (ext, shared_ext))
1547     #endif
1548 michael 945 ))
1549     {
1550     return 1;
1551     }
1552    
1553     return 0;
1554     }
1555    
1556    
1557     /* Initialise and configure a user lt_dladvise opaque object. */
1558    
1559     int
1560     lt_dladvise_init (lt_dladvise *padvise)
1561     {
1562     lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
1563     *padvise = advise;
1564     return (advise ? 0 : 1);
1565     }
1566    
1567     int
1568     lt_dladvise_destroy (lt_dladvise *padvise)
1569     {
1570     if (padvise)
1571     FREE(*padvise);
1572     return 0;
1573     }
1574    
1575     int
1576     lt_dladvise_ext (lt_dladvise *padvise)
1577     {
1578     assert (padvise && *padvise);
1579     (*padvise)->try_ext = 1;
1580     return 0;
1581     }
1582    
1583     int
1584     lt_dladvise_resident (lt_dladvise *padvise)
1585     {
1586     assert (padvise && *padvise);
1587     (*padvise)->is_resident = 1;
1588     return 0;
1589     }
1590    
1591     int
1592     lt_dladvise_local (lt_dladvise *padvise)
1593     {
1594     assert (padvise && *padvise);
1595     (*padvise)->is_symlocal = 1;
1596     return 0;
1597     }
1598    
1599     int
1600     lt_dladvise_global (lt_dladvise *padvise)
1601     {
1602     assert (padvise && *padvise);
1603     (*padvise)->is_symglobal = 1;
1604     return 0;
1605     }
1606    
1607     int
1608     lt_dladvise_preload (lt_dladvise *padvise)
1609     {
1610     assert (padvise && *padvise);
1611     (*padvise)->try_preload_only = 1;
1612     return 0;
1613     }
1614    
1615     /* Libtool-1.5.x interface for loading a new module named FILENAME. */
1616     lt_dlhandle
1617     lt_dlopen (const char *filename)
1618     {
1619     return lt_dlopenadvise (filename, NULL);
1620     }
1621    
1622    
1623     /* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
1624     open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
1625     and if a file is still not found try again with MODULE_EXT appended
1626     instead. */
1627     lt_dlhandle
1628     lt_dlopenext (const char *filename)
1629     {
1630     lt_dlhandle handle = 0;
1631     lt_dladvise advise;
1632    
1633     if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1634     handle = lt_dlopenadvise (filename, advise);
1635    
1636     lt_dladvise_destroy (&advise);
1637     return handle;
1638     }
1639    
1640    
1641     lt_dlhandle
1642     lt_dlopenadvise (const char *filename, lt_dladvise advise)
1643     {
1644     lt_dlhandle handle = 0;
1645     int errors = 0;
1646 michael 1094 const char * saved_error = 0;
1647 michael 945
1648 michael 1094 LT__GETERROR (saved_error);
1649    
1650 michael 945 /* Can't have symbols hidden and visible at the same time! */
1651     if (advise && advise->is_symlocal && advise->is_symglobal)
1652     {
1653     LT__SETERROR (CONFLICTING_FLAGS);
1654     return 0;
1655     }
1656    
1657     if (!filename
1658     || !advise
1659     || !advise->try_ext
1660     || has_library_ext (filename))
1661     {
1662     /* Just incase we missed a code path in try_dlopen() that reports
1663     an error, but forgot to reset handle... */
1664     if (try_dlopen (&handle, filename, NULL, advise) != 0)
1665     return 0;
1666    
1667     return handle;
1668     }
1669     else if (filename && *filename)
1670     {
1671    
1672     /* First try appending ARCHIVE_EXT. */
1673     errors += try_dlopen (&handle, filename, archive_ext, advise);
1674    
1675     /* If we found FILENAME, stop searching -- whether we were able to
1676     load the file as a module or not. If the file exists but loading
1677     failed, it is better to return an error message here than to
1678     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
1679     in the module search path. */
1680     if (handle || ((errors > 0) && !file_not_found ()))
1681     return handle;
1682    
1683     #if defined(LT_MODULE_EXT)
1684     /* Try appending SHLIB_EXT. */
1685 michael 1094 LT__SETERRORSTR (saved_error);
1686 michael 945 errors = try_dlopen (&handle, filename, shlib_ext, advise);
1687    
1688     /* As before, if the file was found but loading failed, return now
1689     with the current error message. */
1690     if (handle || ((errors > 0) && !file_not_found ()))
1691     return handle;
1692     #endif
1693 michael 1257
1694     #if defined(LT_SHARED_EXT)
1695     /* Try appending SHARED_EXT. */
1696     LT__SETERRORSTR (saved_error);
1697     errors = try_dlopen (&handle, filename, shared_ext, advise);
1698    
1699     /* As before, if the file was found but loading failed, return now
1700     with the current error message. */
1701     if (handle || ((errors > 0) && !file_not_found ()))
1702     return handle;
1703     #endif
1704 michael 945 }
1705    
1706     /* Still here? Then we really did fail to locate any of the file
1707     names we tried. */
1708     LT__SETERROR (FILE_NOT_FOUND);
1709     return 0;
1710     }
1711    
1712    
1713     static int
1714     lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1715     const char *entry)
1716     {
1717     error_t error;
1718    
1719     /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1720     pargz_len, NULL, entry) failed with EINVAL. */
1721     if (before)
1722     error = argz_insert (pargz, pargz_len, before, entry);
1723     else
1724     error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1725    
1726     if (error)
1727     {
1728     switch (error)
1729     {
1730     case ENOMEM:
1731     LT__SETERROR (NO_MEMORY);
1732     break;
1733     default:
1734     LT__SETERROR (UNKNOWN);
1735     break;
1736     }
1737     return 1;
1738     }
1739    
1740     return 0;
1741     }
1742    
1743     static int
1744     lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1745     {
1746     char *before = 0;
1747    
1748     assert (pargz);
1749     assert (pargz_len);
1750     assert (entry && *entry);
1751    
1752     if (*pargz)
1753     while ((before = argz_next (*pargz, *pargz_len, before)))
1754     {
1755     int cmp = strcmp (entry, before);
1756    
1757     if (cmp < 0) break;
1758     if (cmp == 0) return 0; /* No duplicates! */
1759     }
1760    
1761     return lt_argz_insert (pargz, pargz_len, before, entry);
1762     }
1763    
1764     static int
1765     lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1766     struct dirent *dp)
1767     {
1768     char *buf = 0;
1769     size_t buf_len = 0;
1770     char *end = 0;
1771     size_t end_offset = 0;
1772     size_t dir_len = 0;
1773     int errors = 0;
1774    
1775     assert (pargz);
1776     assert (pargz_len);
1777     assert (dp);
1778    
1779     dir_len = LT_STRLEN (dirnam);
1780     end = dp->d_name + D_NAMLEN(dp);
1781    
1782     /* Ignore version numbers. */
1783     {
1784     char *p;
1785     for (p = end; p -1 > dp->d_name; --p)
1786     if (strchr (".0123456789", p[-1]) == 0)
1787     break;
1788    
1789     if (*p == '.')
1790     end = p;
1791     }
1792    
1793     /* Ignore filename extension. */
1794     {
1795     char *p;
1796     for (p = end -1; p > dp->d_name; --p)
1797     if (*p == '.')
1798     {
1799     end = p;
1800     break;
1801     }
1802     }
1803    
1804     /* Prepend the directory name. */
1805     end_offset = end - dp->d_name;
1806     buf_len = dir_len + 1+ end_offset;
1807     buf = MALLOC (char, 1+ buf_len);
1808     if (!buf)
1809     return ++errors;
1810    
1811     assert (buf);
1812    
1813     strcpy (buf, dirnam);
1814     strcat (buf, "/");
1815     strncat (buf, dp->d_name, end_offset);
1816     buf[buf_len] = LT_EOS_CHAR;
1817    
1818     /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
1819     if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1820     ++errors;
1821    
1822     FREE (buf);
1823    
1824     return errors;
1825     }
1826    
1827     static int
1828     list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1829     {
1830     DIR *dirp = 0;
1831     int errors = 0;
1832    
1833     assert (dirnam && *dirnam);
1834     assert (pargz);
1835     assert (pargz_len);
1836     assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1837    
1838     dirp = opendir (dirnam);
1839     if (dirp)
1840     {
1841     struct dirent *dp = 0;
1842    
1843     while ((dp = readdir (dirp)))
1844     if (dp->d_name[0] != '.')
1845     if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1846     {
1847     ++errors;
1848     break;
1849     }
1850    
1851     closedir (dirp);
1852     }
1853     else
1854     ++errors;
1855    
1856     return errors;
1857     }
1858    
1859    
1860     /* If there are any files in DIRNAME, call the function passed in
1861     DATA1 (with the name of each file and DATA2 as arguments). */
1862     static int
1863     foreachfile_callback (char *dirname, void *data1, void *data2)
1864     {
1865     file_worker_func *func = *(file_worker_func **) data1;
1866    
1867     int is_done = 0;
1868     char *argz = 0;
1869     size_t argz_len = 0;
1870    
1871     if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1872     goto cleanup;
1873     if (!argz)
1874     goto cleanup;
1875    
1876     {
1877     char *filename = 0;
1878     while ((filename = argz_next (argz, argz_len, filename)))
1879     if ((is_done = (*func) (filename, data2)))
1880     break;
1881     }
1882    
1883     cleanup:
1884     FREE (argz);
1885    
1886     return is_done;
1887     }
1888    
1889    
1890     /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1891     with DATA. The filenames passed to FUNC would be suitable for
1892     passing to lt_dlopenext. The extensions are stripped so that
1893     individual modules do not generate several entries (e.g. libfoo.la,
1894     libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
1895     then the same directories that lt_dlopen would search are examined. */
1896     int
1897     lt_dlforeachfile (const char *search_path,
1898     int (*func) (const char *filename, void *data),
1899     void *data)
1900     {
1901     int is_done = 0;
1902     file_worker_func **fpptr = &func;
1903    
1904     if (search_path)
1905     {
1906     /* If a specific path was passed, search only the directories
1907     listed in it. */
1908     is_done = foreach_dirinpath (search_path, 0,
1909     foreachfile_callback, fpptr, data);
1910     }
1911     else
1912     {
1913     /* Otherwise search the default paths. */
1914     is_done = foreach_dirinpath (user_search_path, 0,
1915     foreachfile_callback, fpptr, data);
1916     if (!is_done)
1917     {
1918     is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1919     foreachfile_callback, fpptr, data);
1920     }
1921    
1922     #if defined(LT_MODULE_PATH_VAR)
1923     if (!is_done)
1924     {
1925     is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1926     foreachfile_callback, fpptr, data);
1927     }
1928     #endif
1929     #if defined(LT_DLSEARCH_PATH)
1930     if (!is_done && *sys_dlsearch_path)
1931     {
1932     is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1933     foreachfile_callback, fpptr, data);
1934     }
1935     #endif
1936     }
1937    
1938     return is_done;
1939     }
1940    
1941     int
1942     lt_dlclose (lt_dlhandle handle)
1943     {
1944     lt_dlhandle cur, last;
1945     int errors = 0;
1946    
1947     /* check whether the handle is valid */
1948     last = cur = handles;
1949     while (cur && handle != cur)
1950     {
1951     last = cur;
1952     cur = cur->next;
1953     }
1954    
1955     if (!cur)
1956     {
1957     LT__SETERROR (INVALID_HANDLE);
1958     ++errors;
1959     goto done;
1960     }
1961    
1962     cur = handle;
1963     cur->info.ref_count--;
1964    
1965     /* Note that even with resident modules, we must track the ref_count
1966     correctly incase the user decides to reset the residency flag
1967     later (even though the API makes no provision for that at the
1968     moment). */
1969     if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1970     {
1971     lt_user_data data = cur->vtable->dlloader_data;
1972    
1973     if (cur != handles)
1974     {
1975     last->next = cur->next;
1976     }
1977     else
1978     {
1979     handles = cur->next;
1980     }
1981    
1982     errors += cur->vtable->module_close (data, cur->module);
1983     errors += unload_deplibs (handle);
1984    
1985     /* It is up to the callers to free the data itself. */
1986     FREE (cur->interface_data);
1987    
1988     FREE (cur->info.filename);
1989     FREE (cur->info.name);
1990     FREE (cur);
1991    
1992     goto done;
1993     }
1994    
1995     if (LT_DLIS_RESIDENT (handle))
1996     {
1997     LT__SETERROR (CLOSE_RESIDENT_MODULE);
1998     ++errors;
1999     }
2000    
2001     done:
2002     return errors;
2003     }
2004    
2005     void *
2006     lt_dlsym (lt_dlhandle place, const char *symbol)
2007     {
2008     size_t lensym;
2009     char lsym[LT_SYMBOL_LENGTH];
2010     char *sym;
2011     void *address;
2012     lt_user_data data;
2013     lt_dlhandle handle;
2014    
2015     if (!place)
2016     {
2017     LT__SETERROR (INVALID_HANDLE);
2018     return 0;
2019     }
2020    
2021     handle = place;
2022    
2023     if (!symbol)
2024     {
2025     LT__SETERROR (SYMBOL_NOT_FOUND);
2026     return 0;
2027     }
2028    
2029     lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2030     + LT_STRLEN (handle->info.name);
2031    
2032     if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2033     {
2034     sym = lsym;
2035     }
2036     else
2037     {
2038     sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2039     if (!sym)
2040     {
2041     LT__SETERROR (BUFFER_OVERFLOW);
2042     return 0;
2043     }
2044     }
2045    
2046     data = handle->vtable->dlloader_data;
2047     if (handle->info.name)
2048     {
2049     const char *saved_error;
2050    
2051     LT__GETERROR (saved_error);
2052    
2053     /* this is a libtool module */
2054     if (handle->vtable->sym_prefix)
2055     {
2056     strcpy(sym, handle->vtable->sym_prefix);
2057     strcat(sym, handle->info.name);
2058     }
2059     else
2060     {
2061     strcpy(sym, handle->info.name);
2062     }
2063    
2064     strcat(sym, "_LTX_");
2065     strcat(sym, symbol);
2066    
2067     /* try "modulename_LTX_symbol" */
2068     address = handle->vtable->find_sym (data, handle->module, sym);
2069     if (address)
2070     {
2071     if (sym != lsym)
2072     {
2073     FREE (sym);
2074     }
2075     return address;
2076     }
2077     LT__SETERRORSTR (saved_error);
2078     }
2079    
2080     /* otherwise try "symbol" */
2081     if (handle->vtable->sym_prefix)
2082     {
2083     strcpy(sym, handle->vtable->sym_prefix);
2084     strcat(sym, symbol);
2085     }
2086     else
2087     {
2088     strcpy(sym, symbol);
2089     }
2090    
2091     address = handle->vtable->find_sym (data, handle->module, sym);
2092     if (sym != lsym)
2093     {
2094     FREE (sym);
2095     }
2096    
2097     return address;
2098     }
2099    
2100     const char *
2101     lt_dlerror (void)
2102     {
2103     const char *error;
2104    
2105     LT__GETERROR (error);
2106     LT__SETERRORSTR (0);
2107    
2108 michael 1094 return error;
2109 michael 945 }
2110    
2111     static int
2112     lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2113     {
2114     int errors = 0;
2115     char *canonical = 0;
2116     char *argz = 0;
2117     size_t argz_len = 0;
2118    
2119     assert (ppath);
2120     assert (dir && *dir);
2121    
2122     if (canonicalize_path (dir, &canonical) != 0)
2123     {
2124     ++errors;
2125     goto cleanup;
2126     }
2127    
2128     assert (canonical && *canonical);
2129    
2130     /* If *PPATH is empty, set it to DIR. */
2131     if (*ppath == 0)
2132     {
2133     assert (!before); /* BEFORE cannot be set without PPATH. */
2134     assert (dir); /* Without DIR, don't call this function! */
2135    
2136     *ppath = lt__strdup (dir);
2137     if (*ppath == 0)
2138     ++errors;
2139    
2140     goto cleanup;
2141     }
2142    
2143     assert (ppath && *ppath);
2144    
2145     if (argzize_path (*ppath, &argz, &argz_len) != 0)
2146     {
2147     ++errors;
2148     goto cleanup;
2149     }
2150    
2151     /* Convert BEFORE into an equivalent offset into ARGZ. This only works
2152     if *PPATH is already canonicalized, and hence does not change length
2153     with respect to ARGZ. We canonicalize each entry as it is added to
2154     the search path, and don't call this function with (uncanonicalized)
2155     user paths, so this is a fair assumption. */
2156     if (before)
2157     {
2158     assert (*ppath <= before);
2159     assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2160    
2161     before = before - *ppath + argz;
2162     }
2163    
2164     if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2165     {
2166     ++errors;
2167     goto cleanup;
2168     }
2169    
2170     argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2171     MEMREASSIGN(*ppath, argz);
2172    
2173     cleanup:
2174     FREE (argz);
2175     FREE (canonical);
2176    
2177     return errors;
2178     }
2179    
2180     int
2181     lt_dladdsearchdir (const char *search_dir)
2182     {
2183     int errors = 0;
2184    
2185     if (search_dir && *search_dir)
2186     {
2187     if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2188     ++errors;
2189     }
2190    
2191     return errors;
2192     }
2193    
2194     int
2195     lt_dlinsertsearchdir (const char *before, const char *search_dir)
2196     {
2197     int errors = 0;
2198    
2199     if (before)
2200     {
2201     if ((before < user_search_path)
2202     || (before >= user_search_path + LT_STRLEN (user_search_path)))
2203     {
2204     LT__SETERROR (INVALID_POSITION);
2205     return 1;
2206     }
2207     }
2208    
2209     if (search_dir && *search_dir)
2210     {
2211     if (lt_dlpath_insertdir (&user_search_path,
2212     (char *) before, search_dir) != 0)
2213     {
2214     ++errors;
2215     }
2216     }
2217    
2218     return errors;
2219     }
2220    
2221     int
2222     lt_dlsetsearchpath (const char *search_path)
2223     {
2224     int errors = 0;
2225    
2226     FREE (user_search_path);
2227    
2228     if (!search_path || !LT_STRLEN (search_path))
2229     {
2230     return errors;
2231     }
2232    
2233     if (canonicalize_path (search_path, &user_search_path) != 0)
2234     ++errors;
2235    
2236     return errors;
2237     }
2238    
2239     const char *
2240     lt_dlgetsearchpath (void)
2241     {
2242     const char *saved_path;
2243    
2244     saved_path = user_search_path;
2245    
2246     return saved_path;
2247     }
2248    
2249     int
2250     lt_dlmakeresident (lt_dlhandle handle)
2251     {
2252     int errors = 0;
2253    
2254     if (!handle)
2255     {
2256     LT__SETERROR (INVALID_HANDLE);
2257     ++errors;
2258     }
2259     else
2260     {
2261     handle->info.is_resident = 1;
2262     }
2263    
2264     return errors;
2265     }
2266    
2267     int
2268     lt_dlisresident (lt_dlhandle handle)
2269     {
2270     if (!handle)
2271     {
2272     LT__SETERROR (INVALID_HANDLE);
2273     return -1;
2274     }
2275    
2276     return LT_DLIS_RESIDENT (handle);
2277     }
2278    
2279    
2280    
2281     /* --- MODULE INFORMATION --- */
2282    
2283     typedef struct {
2284     const char *id_string;
2285     lt_dlhandle_interface *iface;
2286     } lt__interface_id;
2287    
2288     lt_dlinterface_id
2289     lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2290     {
2291     lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2292    
2293     /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2294     can then be detected with lt_dlerror() if we return 0. */
2295     if (interface_id)
2296     {
2297     interface_id->id_string = lt__strdup (id_string);
2298     if (!interface_id->id_string)
2299     FREE (interface_id);
2300     else
2301     interface_id->iface = iface;
2302     }
2303    
2304     return (lt_dlinterface_id) interface_id;
2305     }
2306    
2307     void lt_dlinterface_free (lt_dlinterface_id key)
2308     {
2309     lt__interface_id *interface_id = (lt__interface_id *)key;
2310     FREE (interface_id->id_string);
2311     FREE (interface_id);
2312     }
2313    
2314     void *
2315     lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2316     {
2317     int n_elements = 0;
2318     void *stale = (void *) 0;
2319     lt_dlhandle cur = handle;
2320     int i;
2321    
2322     if (cur->interface_data)
2323     while (cur->interface_data[n_elements].key)
2324     ++n_elements;
2325    
2326     for (i = 0; i < n_elements; ++i)
2327     {
2328     if (cur->interface_data[i].key == key)
2329     {
2330     stale = cur->interface_data[i].data;
2331     break;
2332     }
2333     }
2334    
2335     /* Ensure that there is enough room in this handle's interface_data
2336     array to accept a new element (and an empty end marker). */
2337     if (i == n_elements)
2338     {
2339     lt_interface_data *temp
2340     = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2341    
2342     if (!temp)
2343     {
2344     stale = 0;
2345     goto done;
2346     }
2347    
2348     cur->interface_data = temp;
2349    
2350     /* We only need this if we needed to allocate a new interface_data. */
2351     cur->interface_data[i].key = key;
2352     cur->interface_data[1+ i].key = 0;
2353     }
2354    
2355     cur->interface_data[i].data = data;
2356    
2357     done:
2358     return stale;
2359     }
2360    
2361     void *
2362     lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2363     {
2364     void *result = (void *) 0;
2365     lt_dlhandle cur = handle;
2366    
2367     /* Locate the index of the element with a matching KEY. */
2368     if (cur->interface_data)
2369     {
2370     int i;
2371     for (i = 0; cur->interface_data[i].key; ++i)
2372     {
2373     if (cur->interface_data[i].key == key)
2374     {
2375     result = cur->interface_data[i].data;
2376     break;
2377     }
2378     }
2379     }
2380    
2381     return result;
2382     }
2383    
2384     const lt_dlinfo *
2385     lt_dlgetinfo (lt_dlhandle handle)
2386     {
2387     if (!handle)
2388     {
2389     LT__SETERROR (INVALID_HANDLE);
2390     return 0;
2391     }
2392    
2393     return &(handle->info);
2394     }
2395    
2396    
2397     lt_dlhandle
2398     lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2399     {
2400     lt_dlhandle handle = place;
2401     lt__interface_id *iterator = (lt__interface_id *) iface;
2402    
2403     assert (iface); /* iface is a required argument */
2404    
2405     if (!handle)
2406     handle = handles;
2407     else
2408     handle = handle->next;
2409    
2410     /* advance while the interface check fails */
2411     while (handle && iterator->iface
2412     && ((*iterator->iface) (handle, iterator->id_string) != 0))
2413     {
2414     handle = handle->next;
2415     }
2416    
2417     return handle;
2418     }
2419    
2420    
2421     lt_dlhandle
2422     lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2423     {
2424     lt_dlhandle handle = 0;
2425    
2426     assert (iface); /* iface is a required argument */
2427    
2428     while ((handle = lt_dlhandle_iterate (iface, handle)))
2429     {
2430     lt_dlhandle cur = handle;
2431     if (cur && cur->info.name && streq (cur->info.name, module_name))
2432     break;
2433     }
2434    
2435     return handle;
2436     }
2437    
2438    
2439     int
2440     lt_dlhandle_map (lt_dlinterface_id iface,
2441     int (*func) (lt_dlhandle handle, void *data), void *data)
2442     {
2443     lt__interface_id *iterator = (lt__interface_id *) iface;
2444     lt_dlhandle cur = handles;
2445    
2446     assert (iface); /* iface is a required argument */
2447    
2448     while (cur)
2449     {
2450     int errorcode = 0;
2451    
2452     /* advance while the interface check fails */
2453     while (cur && iterator->iface
2454     && ((*iterator->iface) (cur, iterator->id_string) != 0))
2455     {
2456     cur = cur->next;
2457     }
2458    
2459     if ((errorcode = (*func) (cur, data)) != 0)
2460     return errorcode;
2461     }
2462    
2463     return 0;
2464     }

Properties

Name Value
svn:eol-style native