1 /* search.c
2 
3    Free software by Richard W.E. Furse. Do with as you will. No
4    warranty. */
5 
6 /*****************************************************************************/
7 
8 #include <dirent.h>
9 #include <dlfcn.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 
16 /*****************************************************************************/
17 
18 #include "ladspa.h"
19 #include "utils.h"
20 
21 /*****************************************************************************/
22 
23 /* Search just the one directory. */
24 static void
LADSPADirectoryPluginSearch(const char * pcDirectory,LADSPAPluginSearchCallbackFunction fCallbackFunction)25 LADSPADirectoryPluginSearch
26 (const char * pcDirectory,
27  LADSPAPluginSearchCallbackFunction fCallbackFunction) {
28 
29   char * pcFilename;
30   DIR * psDirectory;
31   LADSPA_Descriptor_Function fDescriptorFunction;
32   long lDirLength;
33   long iNeedSlash;
34   struct dirent * psDirectoryEntry;
35   void * pvPluginHandle;
36 
37   lDirLength = strlen(pcDirectory);
38   if (!lDirLength)
39     return;
40   if (pcDirectory[lDirLength - 1] == '/')
41     iNeedSlash = 0;
42   else
43     iNeedSlash = 1;
44 
45   psDirectory = opendir(pcDirectory);
46   if (!psDirectory)
47     return;
48 
49   while (1) {
50 
51     psDirectoryEntry = readdir(psDirectory);
52     if (!psDirectoryEntry) {
53       closedir(psDirectory);
54       return;
55     }
56 
57     pcFilename = malloc(lDirLength
58 			+ strlen(psDirectoryEntry->d_name)
59 			+ 1 + iNeedSlash);
60     strcpy(pcFilename, pcDirectory);
61     if (iNeedSlash)
62       strcat(pcFilename, "/");
63     strcat(pcFilename, psDirectoryEntry->d_name);
64 
65     pvPluginHandle = dlopen(pcFilename, RTLD_LAZY);
66     if (pvPluginHandle) {
67       /* This is a file and the file is a shared library! */
68 
69       dlerror();
70       fDescriptorFunction
71 	= (LADSPA_Descriptor_Function)dlsym(pvPluginHandle,
72 					    "ladspa_descriptor");
73       if (dlerror() == NULL && fDescriptorFunction) {
74 	/* We've successfully found a ladspa_descriptor function. Pass
75            it to the callback function. */
76 	fCallbackFunction(pcFilename,
77 			  pvPluginHandle,
78 			  fDescriptorFunction);
79 	free(pcFilename);
80       }
81       else {
82 	/* It was a library, but not a LADSPA one. Unload it. */
83 	dlclose(pvPluginHandle);
84 	free(pcFilename);
85       }
86     }
87   }
88 }
89 
90 /*****************************************************************************/
91 
92 void
LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction)93 LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction) {
94 
95   char * pcBuffer;
96   const char * pcEnd;
97   const char * pcLADSPAPath;
98   const char * pcStart;
99 
100   pcLADSPAPath = getenv("LADSPA_PATH");
101   if (!pcLADSPAPath) {
102     fprintf(stderr,
103 	    "Warning: You do not have a LADSPA_PATH "
104 	    "environment variable set. Defaulting to "
105             EXPAND_AND_STRINGIFY(DEFAULT_LADSPA_PATH)
106             ".\n");
107     pcLADSPAPath = EXPAND_AND_STRINGIFY(DEFAULT_LADSPA_PATH);
108   }
109 
110   pcStart = pcLADSPAPath;
111   while (*pcStart != '\0') {
112     pcEnd = pcStart;
113     while (*pcEnd != ':' && *pcEnd != '\0')
114       pcEnd++;
115 
116     pcBuffer = malloc(1 + pcEnd - pcStart);
117     if (pcEnd > pcStart)
118       strncpy(pcBuffer, pcStart, pcEnd - pcStart);
119     pcBuffer[pcEnd - pcStart] = '\0';
120 
121     LADSPADirectoryPluginSearch(pcBuffer, fCallbackFunction);
122     free(pcBuffer);
123 
124     pcStart = pcEnd;
125     if (*pcStart == ':')
126       pcStart++;
127   }
128 }
129 
130 /*****************************************************************************/
131 
132 /* EOF */
133