~ubuntu-branches/ubuntu/utopic/esorex/utopic-proposed

« back to all changes in this revision

Viewing changes to src/er_pluginlist.c

  • Committer: Package Import Robot
  • Author(s): Ole Streicher
  • Date: 2011-11-25 12:08:00 UTC
  • Revision ID: package-import@ubuntu.com-20111125120800-hb8qatpoxkhv0fne
Tags: upstream-3.9.0
ImportĀ upstreamĀ versionĀ 3.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: er_pluginlist.c,v 1.38 2010/07/09 08:33:06 kbanse Exp $
 
2
 *
 
3
 *   This file is part of the ESO Common Pipeline Library
 
4
 *   Copyright (C) 2001-2006 European Southern Observatory
 
5
 *
 
6
 *   This program is free software; you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU General Public License as published by
 
8
 *   the Free Software Foundation; either version 2 of the License, or
 
9
 *   (at your option) any later version.
 
10
 *
 
11
 *   This program is distributed in the hope that it will be useful,
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *   GNU General Public License for more details.
 
15
 *
 
16
 *   You should have received a copy of the GNU General Public License
 
17
 *   along with this program; if not, write to the Free Software
 
18
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 */
 
20
 
 
21
/*
 
22
 * $Author: kbanse $
 
23
 * $Date: 2010/07/09 08:33:06 $
 
24
 * $Revision: 1.38 $
 
25
 * $Name: esorex-3_9_0 $
 
26
 */
 
27
 
 
28
#ifdef HAVE_CONFIG_H
 
29
#   include <config.h>
 
30
#endif
 
31
 
 
32
#include <stdio.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
#include <errno.h>
 
36
#include <assert.h>
 
37
#include <dirent.h>
 
38
 
 
39
#include <sys/types.h>
 
40
#include <sys/stat.h>
 
41
#include <unistd.h>
 
42
 
 
43
 
 
44
#include "ltdl.h"
 
45
 
 
46
#include <cpl.h>
 
47
 
 
48
#include "er_main.h"
 
49
#include "er_fileutils.h"
 
50
#include "er_stringarray.h"
 
51
#include "er_plugin.h"
 
52
#include "er_pluginlist.h"
 
53
#include "er_paramutils.h"
 
54
 
 
55
extern int  MyOS;               /* 1 = Linux, 0 = Mac OSX */
 
56
 
 
57
/*
 
58
 * Symbolic constants used in the search_directory() function
 
59
 */
 
60
 
 
61
#define INDENT_INCR  2          /* Amount to increment per indentation */
 
62
#define INDENT_STR   "| "       /* String to use for each indentation */
 
63
#define ENTRY_STR    "+-"       /* String to use at the start of each entry */
 
64
#define SEP_STR      "/"        /* Directory separator ("/" on UNIX) */
 
65
 
 
66
/*
 
67
 * symbols S_IFMT as well as S_IFREG seem not to be defined even though the
 
68
 * relevant include files are there ... 
 
69
*/
 
70
 
 
71
#ifndef S_IFMT 
 
72
#define       S_IFMT     0170000   /* bitmask for the file type bitfields */
 
73
#define       S_IFREG    0100000   /* regular file */
 
74
#endif
 
75
 
 
76
 
 
77
/**
 
78
 * @defgroup esorex_pluginlist EsoRex Plugin Listing Functions
 
79
 *
 
80
 * EsoRex Plugin Listing Functions.
 
81
 *
 
82
 */
 
83
 
 
84
/**@{*/
 
85
/*
 
86
 
 
87
*/
 
88
 
 
89
/**********************************************************************/
 
90
/**
 
91
 * @brief
 
92
 *   Test whether a file is a valid plugin file
 
93
 *
 
94
 * @param full_filename
 
95
 *   This is the full filename. That is, it includes the full path
 
96
 *   specification and any extension too.
 
97
 *
 
98
 * @returns
 
99
 *   TRUE if the specified module is valid, or FALSE if not.
 
100
 *
 
101
 * This function tests a fully specified filename to see whether or not
 
102
 * it may be loaded as a dynamic library. 
 
103
 */
 
104
/**********************************************************************/
 
105
 
 
106
static int plugin_valid_file (const char *full_filename)
 
107
 
 
108
{
 
109
char *ext;                                       /* File extension */
 
110
lt_dlhandle module = NULL;                  /* Handle to the dynamic library */
 
111
 
 
112
int (*get_plugin_list) (cpl_pluginlist *) = NULL;
 
113
 
 
114
/*  plugins use extension ".so" also on the Mac ...
 
115
char Linux_ext[] = ".so", Mac_ext[] = ".dylib"; 
 
116
*/
 
117
char Linux_ext[] = ".so", Mac_ext[] = ".so";
 
118
char *fixed_ext;
 
119
 
 
120
 
 
121
ER_TRACE(__func__)
 
122
 
 
123
/* If there was no filename, then return */
 
124
if (full_filename == NULL) return 0;
 
125
 
 
126
/* Get the file extension */
 
127
ext = strrchr (full_filename, '.');
 
128
 
 
129
/* Reject any file which doesn't have the correct file extension */
 
130
if (ext == NULL) return 0;
 
131
 
 
132
/* check against ext of dynamic object libraries:
 
133
   before (Derek) checked against LTDL_SHLIB_EXT, a variable of libtool containing 
 
134
   that string
 
135
   if (strcmp (ext, LTDL_SHLIB_EXT) != 0) return 0; 
 
136
   this variable has disappeard in the new 2.x.y version of libtool (e.g. openSuse 11.1)
 
137
   so now (as of Feb. 5, 2009) we test against fixed char string ".la" which is
 
138
   the extension for dynamic object libraries on Linux systems */
 
139
 
 
140
if (MyOS == 1)                                  /* dynamic libs ext for Linux */
 
141
   fixed_ext = Linux_ext;
 
142
else                                            /* dynamic libs ext for MAc */
 
143
   fixed_ext = Mac_ext;
 
144
if (strcmp (ext, fixed_ext) != 0) return 0;
 
145
 
 
146
 
 
147
/* Attempt to open the file as a dynamic library module 
 
148
   unless we linked statically */
 
149
 
 
150
#ifdef STATIC_LINK
 
151
get_plugin_list = &cpl_plugin_get_info;
 
152
 
 
153
#else
 
154
/* printf("opening %s\n",full_filename); */
 
155
 
 
156
module = lt_dlopen (full_filename);
 
157
 
 
158
/* If this didn't load properly, then return */
 
159
if (!module) 
 
160
   {
 
161
   const char  *dl_errstring;
 
162
 
 
163
   dl_errstring = lt_dlerror();
 
164
   cpl_msg_warning (er_func, "lt_dlopen (%s) returned NULL,\nlt_dlerror() = %s\n",
 
165
                    full_filename,dl_errstring);
 
166
   return 0;
 
167
   }
 
168
 
 
169
 
 
170
/* Check that it has the required plugin function */
 
171
get_plugin_list = (int (*)()) lt_dlsym (module, "cpl_plugin_get_info");
 
172
lt_dlclose (module);                    /* Close the module */
 
173
#endif
 
174
 
 
175
if (get_plugin_list == NULL) return 0;
 
176
 
 
177
/* If we get this far, then it was obviously a valid plugin file */
 
178
return 1;
 
179
 
 
180
}                   
 
181
/*
 
182
 
 
183
*/
 
184
 
 
185
/**********************************************************************/
 
186
/**
 
187
 * @brief Recursively searches a directory tree for plugin files
 
188
 *
 
189
 * @param dirname          The name of the directory to search.
 
190
 * @param list_of_pllibs   A list of filenames of validated plugin
 
191
 *                         libraries. If this function finds any more,
 
192
 *                         then they are added to this list.
 
193
 *
 
194
 * Scans all the files in the specified directory. If any of these are
 
195
 * regular files, then another function is called to check whether or
 
196
 * not they are a valid plugin file. If so, then this filename is added
 
197
 * to the provided @a list_of_pllibs . In the case that one of the
 
198
 * scanned files is actually a directory, then this function is
 
199
 * (recursively) called on that function. That way, evenutally, all
 
200
 * files in or below the original directory are searched.
 
201
 *
 
202
 *
 
203
 *
 
204
 * @todo Implement some check to prevent endless looping, for example,
 
205
 *       in the event of an unforeseen error during the recursive calling
 
206
 *       of this function.
 
207
 *
 
208
 */
 
209
/**********************************************************************/
 
210
 
 
211
static void search_directory (const char * dirname, 
 
212
                              er_stringarray_t * list_of_pllibs )
 
213
 
 
214
{
 
215
struct stat finfo;              /* File information */
 
216
struct dirent *entry;           /* Entry in a given directory listing */
 
217
 
 
218
DIR *dp;                        /* Pointer to a directory */
 
219
char *fqfn;                     /* Fully qualified filename (path+file+ext) */
 
220
 
 
221
static int indent = 0;          /* Level of indentation */
 
222
int valid;                      /* Is the specified file a valid plugin file */
 
223
 
 
224
int filename_len = 4096;        /* the "usual" FILENAME_MAX */
 
225
int status;
 
226
int ldir, lentry;
 
227
 
 
228
 
 
229
 
 
230
ER_TRACE(__func__)
 
231
 
 
232
if (list_of_pllibs == NULL) return;
 
233
 
 
234
 
 
235
if (ER_TRACEFLAG) (void) printf("Directory: %s", dirname);
 
236
 
 
237
dp = opendir (dirname);                 /* Open the directory */
 
238
if (dp == NULL)
 
239
   {
 
240
   cpl_msg_warning (er_func, "Unable to open directory %s", dirname);
 
241
   return;
 
242
   }
 
243
 
 
244
 
 
245
ldir = (int) strlen(dirname);
 
246
fqfn = cpl_malloc ((size_t) filename_len);
 
247
if (fqfn == NULL) return;
 
248
 
 
249
while ((entry = readdir (dp)) != NULL)
 
250
   {
 
251
   /* Ignore hidden files, current directory and parent directory */
 
252
   if (entry->d_name[0] == '.') continue;
 
253
 
 
254
   /* We have a directory, so recursively search it with this function */
 
255
   lentry = (int) strlen(entry->d_name);
 
256
   if ((lentry+ldir+4) > filename_len)  /* ensure enough memory is allocated */
 
257
      {
 
258
      filename_len = (lentry+ldir+4) * 2;
 
259
      er_enlarge("search_directory",&fqfn,filename_len);
 
260
      }
 
261
   (void) sprintf (fqfn, "%s%s%s", dirname, SEP_STR, entry->d_name);
 
262
 
 
263
   /* Get information about the current entry (file) */
 
264
   status = stat (fqfn, &finfo);
 
265
   if (status == 0)
 
266
      {
 
267
      if ((finfo.st_mode & S_IFMT) == S_IFREG)
 
268
         {
 
269
         if (ER_TRACEFLAG) printf("S_IFMT, S_IFREG = %o, %o for %s\n",
 
270
                                  S_IFMT,S_IFREG,fqfn);
 
271
 
 
272
         valid = plugin_valid_file (fqfn);
 
273
         if (valid == TRUE)
 
274
            {
 
275
            /* If we get this far, then we've found a plugin */
 
276
            /* Add it to the list of plugins that we have so far */
 
277
 
 
278
            er_stringarray_append (list_of_pllibs, fqfn);
 
279
            if (ER_TRACEFLAG) printf("%s is a RECIPE...\n",fqfn);
 
280
            }
 
281
         else
 
282
            {
 
283
            if (ER_TRACEFLAG) printf("%s not a recipe...\n",fqfn);
 
284
            }
 
285
         }
 
286
      else if (S_ISDIR (finfo.st_mode))
 
287
         {
 
288
         /* Recursively search any subdirectory that we find */
 
289
         search_directory (fqfn, list_of_pllibs);
 
290
         }
 
291
 
 
292
      }                         /* End if valid status */
 
293
   }                            /* End of while */
 
294
 
 
295
/* Release the memory allocated to the filename */
 
296
 
 
297
cpl_free (fqfn);
 
298
 
 
299
indent -= INDENT_INCR;          /* Decrement the indentation again */
 
300
closedir (dp);
 
301
 
 
302
}                               /* End of search_directory() */
 
303
/*
 
304
 
 
305
*/
 
306
 
 
307
/**********************************************************************/
 
308
/**
 
309
 * @brief Creates a string array of plugin libraries in a given directory
 
310
 *
 
311
 * @param directories_to_search  An array of directory names.
 
312
 *
 
313
 * @returns Pointer to stringarray
 
314
 *
 
315
 * This function establishes a new stringarray, @c list_of_pllibs .
 
316
 * It then calls the @c search_directory function to recursively search
 
317
 * the specified @ directory_to_search . @c search_directory will add
 
318
 * the filenames of any found plugin files to @c list_of_pllibs . When
 
319
 * this operation is complete, the function will return the stringarray.
 
320
 *
 
321
 */
 
322
/**********************************************************************/
 
323
 
 
324
er_stringarray_t *er_pluginlist_create_list (char ** directories_to_search)
 
325
 
 
326
{
 
327
er_stringarray_t *list_of_pllibs;       /* List of plugin library (filenames) */
 
328
er_stringarray_t *reduced_list;         /* List of plugin library (filenames) */
 
329
 
 
330
char **dir_str;                         /* Pointer to the list of directories */
 
331
 
 
332
int i1, i2;                             /* Indices into the plugin list */
 
333
int duplicate;
 
334
 
 
335
 
 
336
 
 
337
ER_TRACE(__func__)
 
338
 
 
339
 
 
340
/* Obviously, we need a directory to search, so bail out if there isn't one */
 
341
 
 
342
if (directories_to_search == NULL) return NULL;
 
343
 
 
344
 
 
345
/* Create a new array of strings to contain any plugin filenames */
 
346
 
 
347
if ((list_of_pllibs = er_stringarray_new ()) == NULL) return NULL;
 
348
 
 
349
for (dir_str = directories_to_search; *dir_str != NULL; dir_str++)
 
350
   {
 
351
   /*
 
352
    * Recursively search the specified directory, adding any found
 
353
    * plugins to the list
 
354
    */
 
355
   search_directory (er_fileutils_tilde_replace (*dir_str),
 
356
                     list_of_pllibs);
 
357
   }
 
358
 
 
359
/* Create a new array of strings for the consolidated list */
 
360
 
 
361
reduced_list = er_stringarray_new ();
 
362
if (reduced_list != NULL)
 
363
   {
 
364
   /* Consolidate the list - there may be duplicate entries */
 
365
   for (i1=0; i1<er_stringarray_size (list_of_pllibs); i1++)
 
366
      {
 
367
      duplicate = 0;
 
368
      for (i2=0; i2<er_stringarray_size (reduced_list); i2++)
 
369
         {
 
370
         if (strcmp (er_stringarray_get (list_of_pllibs, i1),
 
371
                     er_stringarray_get (reduced_list, i2)) == 0)
 
372
 
 
373
            {
 
374
            duplicate = 1;
 
375
            }
 
376
         }
 
377
      if (duplicate == 0)
 
378
         {
 
379
         er_stringarray_append (reduced_list,
 
380
                                er_stringarray_get (list_of_pllibs, i1));
 
381
         }
 
382
      }
 
383
   }
 
384
 
 
385
er_stringarray_delete (list_of_pllibs);
 
386
 
 
387
/* Return the (possibly empty) list of plugin filenames */
 
388
 
 
389
return reduced_list;
 
390
 
 
391
}                               /* End of er_pluginlist_create_list() */
 
392
/*
 
393
 
 
394
*/
 
395
 
 
396
/**********************************************************************/
 
397
/**
 
398
 * @brief  Gets the full pathname of the library containing the named plugin
 
399
 *
 
400
 * @param list_of_pllibs String array of plugin libraries
 
401
 * @param plugin_name    Name to look for in pllibs given in string array
 
402
 *
 
403
 * @returns the length of the library path found,
 
404
 *          or 0, in the case that no suitable library was found
 
405
 *
 
406
 * The function takes a list of plugin library path names, and opens
 
407
 * all of them searching for the named plugin: @c plugin_name . While 
 
408
 * doing this, the funciton also checks for the existence of multiple 
 
409
 * plugins with the same name. Should multiples be found, then the 
 
410
 * function will print a warning message to this effect, indicating 
 
411
 * which one it chose to use.
 
412
 *
 
413
 * The choice is made based on the version number. If the same version 
 
414
 * number exists multiple times, then the first one it finds in the 
 
415
 * library path is used.
 
416
 *
 
417
 */
 
418
/**********************************************************************/
 
419
 
 
420
int er_pluginlist_get_libpath (er_stringarray_t * list_of_pllibs,
 
421
                         const char * plugin_name, char *libpath)
 
422
 
 
423
{
 
424
char *cptr, fully_qualified_library_name[MAXSTRLENCONF];
 
425
 
 
426
lt_dlhandle module = NULL;
 
427
 
 
428
cpl_pluginlist *pl_list = NULL;
 
429
cpl_plugin *pl = NULL;
 
430
 
 
431
int i = 0, e_code = 0;
 
432
int f_report_error = 1;
 
433
int num_copies = 0;
 
434
int num_best = 0;
 
435
int  m;
 
436
 
 
437
int (*get_plugin_list) (cpl_pluginlist *) = NULL;
 
438
 
 
439
 
 
440
unsigned long this_version = 0;
 
441
unsigned long best_version = 0;
 
442
 
 
443
 
 
444
 
 
445
ER_TRACE(__func__)
 
446
 
 
447
fully_qualified_library_name[0] = '\0';
 
448
 
 
449
if (list_of_pllibs == NULL)
 
450
   {
 
451
   cpl_msg_warning (er_func, "Empty plugin list");
 
452
   return 0;
 
453
   }
 
454
 
 
455
 
 
456
for (i=0; i< er_stringarray_size (list_of_pllibs); i++)
 
457
   {
 
458
   cptr = er_stringarray_get (list_of_pllibs, i);
 
459
   m = (int) strlen(cptr);
 
460
   if (m > (MAXSTRLENCONF-1))
 
461
      {
 
462
      cpl_msg_error (er_func, "size of plugin lib > %d ...", MAXSTRLENCONF);
 
463
      return 0;
 
464
      }
 
465
 
 
466
   (void) strcpy(fully_qualified_library_name, cptr);
 
467
 
 
468
#ifdef STATIC_LINK
 
469
   get_plugin_list = &cpl_plugin_get_info;
 
470
 
 
471
#else
 
472
   module = lt_dlopen (fully_qualified_library_name); /* try to open library */ 
 
473
   if (!module)
 
474
      {
 
475
      cpl_msg_error (er_func, "Could not open %s: %s",
 
476
                     fully_qualified_library_name, lt_dlerror ());
 
477
      return 0;
 
478
      }
 
479
 
 
480
   /* get plugin list  */
 
481
 
 
482
   get_plugin_list = (int (*)()) lt_dlsym (module, "cpl_plugin_get_info");
 
483
#endif
 
484
 
 
485
   /* Cannot use lt_dlerror due to bug in 1.4.2 version of libtool */
 
486
 
 
487
   if (get_plugin_list == NULL)
 
488
      {
 
489
      cpl_msg_error (er_func, "Could not find cpl_plugin_get_info() "
 
490
                     "index function for plugin library (%s): %s",
 
491
                     fully_qualified_library_name, lt_dlerror ());
 
492
#ifdef STATIC_LINK
 
493
#else
 
494
      lt_dlclose(module);
 
495
#endif
 
496
      return 0;
 
497
      }
 
498
 
 
499
   /* Make a pluginlist containing all the plugins in the library */
 
500
 
 
501
   pl_list = cpl_pluginlist_new ();
 
502
   e_code = get_plugin_list (pl_list);
 
503
   if (e_code != 0)
 
504
      {
 
505
      cpl_msg_warning (er_func,
 
506
                       "Unexpected error (%d) in recovering a pluginlist from "
 
507
                       "library '%s'", e_code,
 
508
                       fully_qualified_library_name);
 
509
      }
 
510
 
 
511
   /* Check the "one-plugin-per-library" assumption */
 
512
 
 
513
   m = cpl_pluginlist_get_size (pl_list);
 
514
   if (m == 0)
 
515
      {
 
516
      cpl_msg_warning (er_func, "No plugins contained within "
 
517
                       "library '%s'", fully_qualified_library_name);
 
518
      }
 
519
   else if (m > 1)
 
520
      {
 
521
      cpl_msg_warning (er_func, "Multiple plugins contained within "
 
522
                       "library '%s'", fully_qualified_library_name);
 
523
      }
 
524
 
 
525
   /* Once we have a valid library, fetch the plugin out of it */
 
526
 
 
527
   pl = cpl_pluginlist_find (pl_list, plugin_name);
 
528
 
 
529
   /* Double check again, to make sure we got it */
 
530
 
 
531
   if (pl != NULL)
 
532
      {         /* Increment a counter of all instances that we've found */
 
533
      num_copies++;
 
534
 
 
535
      /* Get the version number of this plugin */
 
536
 
 
537
      this_version = cpl_plugin_get_version (pl);
 
538
 
 
539
      /* Make sure the version number is value (i.e. non-zero) */
 
540
 
 
541
      if (this_version == 0)
 
542
         {
 
543
         cpl_msg_warning (er_func,
 
544
                 "Recipe '%s' (in library '%s') has an invalid version number",
 
545
                 plugin_name, fully_qualified_library_name);
 
546
         }
 
547
 
 
548
      /* Now see if this version is later than the best we have so far */
 
549
 
 
550
      if (this_version > best_version)
 
551
         {                                      /* size check done above ... */
 
552
         (void) strcpy(libpath, fully_qualified_library_name);
 
553
         best_version = this_version;
 
554
         num_best = 1;
 
555
         f_report_error = 0;
 
556
         }
 
557
      else if (this_version == best_version)
 
558
         {
 
559
         num_best++;
 
560
         f_report_error = 1;
 
561
         }
 
562
      }
 
563
   cpl_pluginlist_delete (pl_list);
 
564
 
 
565
#ifdef STATIC_LINK
 
566
#else
 
567
   lt_dlclose(module);
 
568
#endif
 
569
   }
 
570
 
 
571
if (num_best > 1)
 
572
   {
 
573
   cpl_msg_error (er_func,
 
574
       "Multiple copies (%d) of the latest version of recipe '%s' were found. "
 
575
       "Using path '%s' ('%s' version %lu)", num_best, plugin_name, libpath,
 
576
                                             plugin_name, best_version);
 
577
   }
 
578
else if (num_copies > 1)
 
579
   {
 
580
   cpl_msg_warning (er_func,
 
581
       "Older copies (%d) of recipe '%s' were also found. "
 
582
       "Using latest version, path '%s' ('%s' version %lu)",
 
583
       (num_copies - 1), plugin_name, libpath, plugin_name, best_version);
 
584
   }
 
585
 
 
586
return ((int)strlen(libpath));
 
587
 
 
588
}                               /* End of er_pluginlist_get_libpath() */
 
589
/*
 
590
 
 
591
*/
 
592
 
 
593
/**********************************************************************/
 
594
/**
 
595
 * @brief  Gets a plugin, of a given name, from a given library.
 
596
 *
 
597
 * @param list_of_pllibs String array of pllibs
 
598
 * @param plugin_name    Name of plugin to recover.
 
599
 * @param module         (output) A handle to the plugin library. This
 
600
 *                       handle should be close (with lt_dlclose) when
 
601
 *                       the returned plugin is no longer used. If the
 
602
 *                       requested plugin could not be found, NULL is
 
603
 *                       returned.
 
604
 *
 
605
 * @returns Pointer to Plugin, or NULL if the requested plugin could not 
 
606
 *          be found
 
607
 *
 
608
 * @warning At this stage, this function is only experimental. It should
 
609
 *          not be used in the normal EsoRex build/execution.
 
610
 *
 
611
 */
 
612
/**********************************************************************/
 
613
 
 
614
cpl_plugin *er_pluginlist_get_plugin (const char * library_name,
 
615
                                      const char * plugin_name,
 
616
                                      lt_dlhandle *module)
 
617
 
 
618
{
 
619
const char *fn = "er_pluginlist_get_plugin";
 
620
cpl_pluginlist *pl_list = NULL;
 
621
cpl_plugin *pl = NULL, *pl_copy = NULL;
 
622
 
 
623
int mm, e_code = 0;
 
624
int (*get_plugin_list) (cpl_pluginlist *) = NULL;
 
625
 
 
626
 
 
627
 
 
628
ER_TRACE(__func__)
 
629
 
 
630
if (library_name == NULL)
 
631
   {
 
632
   cpl_msg_error (fn, "NULL pointer received instead of library_name");
 
633
   return NULL;
 
634
   }
 
635
if (plugin_name == NULL)
 
636
   {
 
637
   cpl_msg_error (fn, "NULL pointer received instead of plugin_name");
 
638
   return NULL;
 
639
   }
 
640
 
 
641
pl_list = cpl_pluginlist_new ();
 
642
 
 
643
/* Try to open library, unless we link statically */
 
644
 
 
645
#ifdef STATIC_LINK
 
646
get_plugin_list = &cpl_plugin_get_info;
 
647
 
 
648
#else
 
649
*module = lt_dlopen (library_name);
 
650
if (!(*module))
 
651
   {
 
652
   cpl_msg_error (fn, "Could not open %s: %s", library_name, lt_dlerror ());
 
653
   return NULL;
 
654
   }
 
655
 
 
656
 
 
657
/* get plugin list */
 
658
 
 
659
get_plugin_list = (int (*)()) lt_dlsym (*module, "cpl_plugin_get_info");
 
660
#endif
 
661
 
 
662
 
 
663
/* lt_dlclose (module) will be done in caller routine plugin_process_plugin() */
 
664
 
 
665
if (get_plugin_list == NULL)
 
666
   {
 
667
   cpl_msg_error (fn, "Could not find cpl_plugin_get_info() "
 
668
                  "index function for plugin library (%s): %s",
 
669
                  library_name, lt_dlerror ());
 
670
   return NULL;
 
671
   }
 
672
 
 
673
pl_copy = NULL;
 
674
e_code = get_plugin_list (pl_list);
 
675
 
 
676
if (e_code != 0)
 
677
   {
 
678
   cpl_msg_warning (fn,
 
679
                    "Unexpected error (%d) in recovering a pluginlist from "
 
680
                    "library '%s'", e_code, library_name);
 
681
   goto end_of_it;
 
682
   }
 
683
 
 
684
/* Check the "one-plugin-per-library" assumption */
 
685
 
 
686
mm = cpl_pluginlist_get_size (pl_list);
 
687
if (mm > 1)
 
688
   {
 
689
   cpl_msg_warning (fn, "Multiple plugins contained within "
 
690
                    "library '%s'", library_name);
 
691
   }
 
692
else if (mm < 1)
 
693
   {
 
694
   cpl_msg_warning (fn, "No plugins contained within "
 
695
                    "library '%s'", library_name);
 
696
   goto end_of_it;
 
697
   }
 
698
 
 
699
 
 
700
/* Now search for the plugin in the specified library */
 
701
 
 
702
pl = cpl_pluginlist_find (pl_list, plugin_name);
 
703
 
 
704
 
 
705
/* If found, make a copy of it (remains NULL otherwise) */
 
706
 
 
707
if (pl != NULL)
 
708
   {
 
709
   pl_copy = cpl_plugin_new ();
 
710
   e_code = cpl_plugin_copy (pl_copy, pl);
 
711
   if (e_code != CPL_ERROR_NONE)
 
712
      {
 
713
      cpl_msg_error (fn, "Failed to make internal copy of plugin");
 
714
      }
 
715
   }
 
716
 
 
717
/* Delete the plugin list, and return the pointer to the copy */
 
718
 
 
719
end_of_it:
 
720
cpl_pluginlist_delete (pl_list);
 
721
 
 
722
return pl_copy;
 
723
}                               /* End of er_pluginlist_get_plugin() */
 
724
/*
 
725
 
 
726
*/
 
727
 
 
728
/**********************************************************************/
 
729
/**
 
730
 * @brief  Creates a string array of the names of available plugins.
 
731
 *
 
732
 * @param  list_of_pllibs   String array of pllibs
 
733
 * @retval list_of_plugins  String array of plugin names
 
734
 *
 
735
 * This function creates a string array of all plugins contained in list
 
736
 * of pllibs specified in a string array. The function does not display
 
737
 * these in any way.
 
738
 */
 
739
/**********************************************************************/
 
740
 
 
741
void er_pluginlist_create_cache (er_stringarray_t * list_of_pllibs,
 
742
                   er_stringarray_t * list_of_plugin_names)
 
743
 
 
744
{
 
745
const char *fn = "er_pluginlist_create_cache";
 
746
 
 
747
char *cptr, fully_qualified_library_name[MAXSTRLENCONF];
 
748
 
 
749
cpl_plugin *tplugin = NULL;
 
750
 
 
751
lt_dlhandle module = NULL;
 
752
 
 
753
int m, e_code = 0, i = 0;
 
754
int (*get_plugin_list) (cpl_pluginlist *) = NULL;
 
755
 
 
756
 
 
757
 
 
758
ER_TRACE(fn)
 
759
 
 
760
if (list_of_pllibs == NULL) return;
 
761
 
 
762
fully_qualified_library_name[0] = '\0';
 
763
 
 
764
for (i = 0; i < er_stringarray_size (list_of_pllibs); i++)
 
765
   {
 
766
   cpl_pluginlist *pl_list = cpl_pluginlist_new ();
 
767
   cptr = er_stringarray_get (list_of_pllibs, i);
 
768
 
 
769
   m = (int) strlen(cptr);
 
770
   if (m > (MAXSTRLENCONF-1))
 
771
      {
 
772
      cpl_msg_error (er_func, "size of plugin lib > %d ...", MAXSTRLENCONF);
 
773
      return;
 
774
      }
 
775
   (void) strcpy(fully_qualified_library_name,cptr);
 
776
 
 
777
 
 
778
   /* try to open library, unless we link statically */
 
779
 
 
780
#ifdef STATIC_LINK
 
781
   get_plugin_list = &cpl_plugin_get_info;
 
782
 
 
783
#else
 
784
   module = lt_dlopen (fully_qualified_library_name);
 
785
   if (!module)
 
786
      {
 
787
      cpl_msg_error (fn, "Could not open %s: %s",
 
788
                     fully_qualified_library_name, lt_dlerror ());
 
789
      cpl_pluginlist_delete (pl_list);
 
790
      return;
 
791
      }
 
792
 
 
793
   /* get plugin list */
 
794
 
 
795
   get_plugin_list = (int (*)()) lt_dlsym (module, "cpl_plugin_get_info");
 
796
#endif
 
797
 
 
798
   if (get_plugin_list == NULL)
 
799
      {
 
800
      cpl_msg_error (fn, "Could not find cpl_plugin_get_info()"
 
801
                     " of plugin library %s",
 
802
                     fully_qualified_library_name);
 
803
      cpl_pluginlist_delete (pl_list);
 
804
#ifdef STATIC_LINK
 
805
#else
 
806
      lt_dlclose(module);
 
807
#endif
 
808
      return;
 
809
      }
 
810
 
 
811
   e_code = get_plugin_list (pl_list);
 
812
 
 
813
   tplugin = cpl_pluginlist_get_first (pl_list);
 
814
   while (tplugin != NULL)
 
815
      {
 
816
      if (cpl_plugin_get_api (tplugin) == CPL_PLUGIN_API)
 
817
         {
 
818
         if (cpl_plugin_get_type (tplugin) & CPL_PLUGIN_TYPE_RECIPE)
 
819
            {
 
820
            er_stringarray_append (list_of_plugin_names,
 
821
                                        (char *) cpl_plugin_get_name (tplugin));
 
822
            }
 
823
         }
 
824
 
 
825
      tplugin = cpl_pluginlist_get_next (pl_list);
 
826
 
 
827
      }                         /* End of while() */
 
828
 
 
829
   cpl_pluginlist_delete (pl_list);
 
830
 
 
831
#ifdef STATIC_LINK
 
832
#else
 
833
   lt_dlclose(module);
 
834
#endif
 
835
 
 
836
   }                            /* End of for(each name in list_of_pllibs) */
 
837
 
 
838
return;
 
839
 
 
840
}                               /* End of er_pluginlist_create_cache() */
 
841
/*
 
842
 
 
843
*/
 
844
 
 
845
/**********************************************************************/
 
846
/**
 
847
 * @brief  Neatly print a list of all the plugins.
 
848
 *
 
849
 * @param  list_of_pllibs   String array of plugin library names.
 
850
 *
 
851
 * This function will take a stringarray, @a list_of_pllibs , which
 
852
 * contains the names of all the plugin files (i.e. the dynamic libraries)
 
853
 * which are visible within the current path. It then extracts from these
 
854
 * files the plugins themselves, and makes use of CPL calls to access
 
855
 * the name and synopsis of each individual file, before printing them.
 
856
 */
 
857
/**********************************************************************/
 
858
 
 
859
void er_pluginlist_print_list (er_stringarray_t * list_of_pllibs)
 
860
 
 
861
{
 
862
char *ccptr, fully_qualified_library_name[MAXSTRLENCONF];
 
863
 
 
864
cpl_plugin *tplugin = NULL;
 
865
 
 
866
lt_dlhandle module = NULL;
 
867
 
 
868
int (*get_plugin_list) (cpl_pluginlist *) = NULL;
 
869
 
 
870
int m, e_code = 0, i = 0;
 
871
int num_plugins = 0;
 
872
 
 
873
 
 
874
 
 
875
ER_TRACE(__func__)
 
876
 
 
877
fully_qualified_library_name[0] = '\0';
 
878
 
 
879
if (list_of_pllibs == NULL) return;
 
880
 
 
881
 
 
882
(void) printf("List of Available Recipes :\n\n");
 
883
 
 
884
/* Loop through each dynamic library file that we have */
 
885
 
 
886
for (i=0; i < er_stringarray_size(list_of_pllibs); i++)
 
887
   {
 
888
   cpl_pluginlist *pl_list = cpl_pluginlist_new ();
 
889
 
 
890
   ccptr = er_stringarray_get (list_of_pllibs, i);
 
891
   m = (int) strlen(ccptr);
 
892
   if (m > (MAXSTRLENCONF-1))
 
893
      {
 
894
      cpl_msg_error (er_func, "size of plugin lib > %d ...", MAXSTRLENCONF);
 
895
      return;
 
896
      }
 
897
 
 
898
   (void) strcpy(fully_qualified_library_name,ccptr);
 
899
 
 
900
#ifdef STATIC_LINK
 
901
   get_plugin_list = &cpl_plugin_get_info;
 
902
 
 
903
#else
 
904
   module = lt_dlopen (fully_qualified_library_name); /* try to open library */
 
905
   if (!module)
 
906
      {
 
907
      cpl_msg_error (er_func, "Could not open %s: %s",
 
908
                     fully_qualified_library_name, lt_dlerror ());
 
909
      cpl_pluginlist_delete (pl_list);
 
910
      return;
 
911
      }
 
912
 
 
913
   get_plugin_list = (int (*)()) lt_dlsym (module, "cpl_plugin_get_info");
 
914
#endif
 
915
 
 
916
   if (get_plugin_list == NULL)
 
917
      {
 
918
      cpl_msg_error (er_func, "Could not find the cpl_plugin_get_info() function"
 
919
                     " of plugin library %s", fully_qualified_library_name);
 
920
      cpl_pluginlist_delete (pl_list);
 
921
 
 
922
#ifdef STATIC_LINK
 
923
#else
 
924
      lt_dlclose(module);
 
925
#endif
 
926
      return;
 
927
      }
 
928
 
 
929
   e_code = get_plugin_list (pl_list);
 
930
   if (e_code != CPL_ERROR_NONE)
 
931
      {
 
932
      cpl_msg_error (er_func, "Unable to read plugin list");
 
933
      cpl_pluginlist_delete (pl_list);
 
934
 
 
935
#ifdef STATIC_LINK
 
936
#else
 
937
      lt_dlclose(module);
 
938
#endif
 
939
      return;
 
940
      }
 
941
 
 
942
   /* Get the first plugin in the list */
 
943
 
 
944
   tplugin = cpl_pluginlist_get_first (pl_list);
 
945
 
 
946
   /* Loop through all the plugins that we can find */
 
947
 
 
948
   while (tplugin != NULL)
 
949
      {         /* Check that we are printing appropriate plugins only */
 
950
      if (cpl_plugin_get_api (tplugin) != CPL_PLUGIN_API) continue;
 
951
      if (!(cpl_plugin_get_type (tplugin) & CPL_PLUGIN_TYPE_RECIPE)) continue;
 
952
 
 
953
      er_paramutils_print_key_desc ("", cpl_plugin_get_name (tplugin),
 
954
                                    cpl_plugin_get_synopsis (tplugin));
 
955
 
 
956
      num_plugins++;            /* Increment the plugin counter */
 
957
 
 
958
                                /* Get the next plugin in the list */
 
959
      tplugin = cpl_pluginlist_get_next (pl_list);
 
960
      } 
 
961
 
 
962
   cpl_pluginlist_delete (pl_list);
 
963
 
 
964
#ifdef STATIC_LINK
 
965
#else
 
966
   lt_dlclose(module);
 
967
#endif
 
968
   }                            /* End of for(each name in list_of_pllibs) */
 
969
 
 
970
/* Print a warning message if no plugins were listed */
 
971
 
 
972
if (num_plugins == 0)
 
973
   (void) printf("  No recipes were found in the specified recipe directory.\n");
 
974
 
 
975
(void) printf("\n");
 
976
 
 
977
return;
 
978
 
 
979
}                               /* End of er_pluginlist_print_list() */
 
980
 
 
981
 
 
982
/**@}*/
 
983
 
 
984
 
 
985
/* End of file */