diff options
-rw-r--r-- | include/local-def.h | 3 | ||||
-rw-r--r-- | nbproject/private/private.xml | 11 | ||||
-rw-r--r-- | src/config.c | 12 | ||||
-rw-r--r-- | src/main.c | 14 | ||||
-rw-r--r-- | src/rest-api.c | 124 |
5 files changed, 101 insertions, 63 deletions
diff --git a/include/local-def.h b/include/local-def.h index 843805f8..d278dc47 100644 --- a/include/local-def.h +++ b/include/local-def.h @@ -63,6 +63,7 @@ #define DEFLT_CACHE_TIMEOUT 100000 // default Static File Chache [Client Side Cache 100000~=1day] #define DEFLT_AUTH_TOKEN NULL // expect for debug should == NULL #define DEFLT_HTTP_TIMEOUT 15 // Max MibMicroHttp timeout +#define AFB_MAX_PLUGINS 20 // Max number of plugins for a given binder typedef int BOOL; #ifndef FALSE @@ -170,7 +171,7 @@ typedef struct { int localhostOnly; int httpdPort; char *smack; // smack label - char *plugins; // list of requested plugins + char *ldpaths; // list of plugins directories char *rootdir; // base dir for httpd file download char *rootbase; // Angular HTML5 base URL char *rootapi; // Base URL for REST APIs diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index 88244563..795635d6 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -6,15 +6,6 @@ </data> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> - <group> - <file>file:/home/fulup/Workspace/afb-daemon/plugins/samples/SamplePost.c</file> - <file>file:/home/fulup/Workspace/afb-daemon/src/session.c</file> - <file>file:/home/fulup/Workspace/afb-daemon/src/helper-api.c</file> - <file>file:/home/fulup/Workspace/afb-daemon/src/main.c</file> - <file>file:/home/fulup/Workspace/afb-daemon/include/local-def.h</file> - <file>file:/home/fulup/Workspace/afb-daemon/include/proto-def.h</file> - <file>file:/home/fulup/Workspace/afb-daemon/src/rest-api.c</file> - <file>file:/home/fulup/Workspace/afb-daemon/src/config.c</file> - </group> + <group/> </open-files> </project-private> diff --git a/src/config.c b/src/config.c index 815d11f3..f818f7ac 100644 --- a/src/config.c +++ b/src/config.c @@ -114,10 +114,10 @@ PUBLIC AFB_error configLoadFile (AFB_session * session, AFB_config *cliconfig) { session->config->smack= cliconfig->smack; } - if (cliconfig->plugins == NULL) { - session->config->plugins = PLUGIN_INSTALL_DIR; + if (cliconfig->ldpaths == NULL) { + session->config->ldpaths = PLUGIN_INSTALL_DIR; } else { - session->config->plugins= cliconfig->plugins; + session->config->ldpaths= cliconfig->ldpaths; } // if no session dir create a default path from rootdir @@ -190,8 +190,8 @@ PUBLIC AFB_error configLoadFile (AFB_session * session, AFB_config *cliconfig) { session->config->smack = strdup (json_object_get_string (value)); } - if (!cliconfig->plugins && json_object_object_get_ex (AFBConfig, "plugins", &value)) { - session->config->plugins = strdup (json_object_get_string (value)); + if (!cliconfig->ldpaths && json_object_object_get_ex (AFBConfig, "plugins", &value)) { + session->config->ldpaths = strdup (json_object_get_string (value)); } if (!cliconfig->setuid && json_object_object_get_ex (AFBConfig, "setuid", &value)) { @@ -256,7 +256,7 @@ PUBLIC void configStoreFile (AFB_session * session) { json_object_object_add (AFBConfig, "rootapi" , json_object_new_string (session->config->rootapi)); json_object_object_add (AFBConfig, "rootbase" , json_object_new_string (session->config->rootbase)); json_object_object_add (AFBConfig, "smack" , json_object_new_string (session->config->smack)); - json_object_object_add (AFBConfig, "plugins" , json_object_new_string (session->config->plugins)); + json_object_object_add (AFBConfig, "plugins" , json_object_new_string (session->config->ldpaths)); json_object_object_add (AFBConfig, "sessiondir" , json_object_new_string (session->config->sessiondir)); json_object_object_add (AFBConfig, "pidfile" , json_object_new_string (session->config->pidfile)); json_object_object_add (AFBConfig, "setuid" , json_object_new_string (session->config->setuid)); @@ -73,7 +73,7 @@ static sigjmp_buf exitPoint; // context save for set/longjmp #define SET_SMACK 140 #define SET_AUTH_TOKEN 141 - #define SET_PLUGINS 142 + #define SET_LDPATH 142 #define SET_APITIMEOUT 143 #define SET_CNTXTIMEOUT 144 @@ -107,8 +107,8 @@ static AFB_options cliOptions [] = { {SET_CONFIG_SAVE ,0,"save" , "Save config on disk [default no]"}, {SET_CONFIG_EXIT ,0,"saveonly" , "Save config on disk and then exit"}, - {SET_SMACK ,1,"smack" , "Set Smack Label [default demo]"}, - {SET_PLUGINS ,1,"plugins" , "Load Plugins from dir [default = PLUGIN_INSTALL_DIR"}, + // {SET_SMACK ,1,"smack" , "Set Smack Label [default demo]"}, + {SET_LDPATH ,1,"ldpaths" , "Load Plugins from dir1:dir2:... [default = PLUGIN_INSTALL_DIR"}, {SET_AUTH_TOKEN ,1,"token" , "Initial Secret [default=no-session, --token="" for session without authentication]"}, {DISPLAY_VERSION ,0,"version" , "Display version and copyright"}, @@ -159,7 +159,7 @@ void signalQuit (int signum) { fprintf (stderr," --%-15s %s\n", command, cliOptions[ind].help); } } - fprintf (stderr,"Example:\n %s\\\n --verbose --port=1234 --smack=xxxx --token='azerty' --plugins=build/plugins\n", name); + fprintf (stderr,"Example:\n %s\\\n --verbose --port=1234 --token='azerty' --ldpaths=build/plugins:/usr/lib64/agl/plugins\n", name); } // end printHelp /*---------------------------------------------------------- @@ -355,9 +355,9 @@ int main(int argc, char *argv[]) { cliconfig.token = optarg; break; - case SET_PLUGINS: + case SET_LDPATH: if (optarg == 0) goto needValueForOption; - cliconfig.plugins = optarg; + cliconfig.ldpaths = optarg; break; case SET_PID_FILE: @@ -589,7 +589,7 @@ int main(int argc, char *argv[]) { normalExit: closeSession (session); // try to close everything before leaving if (verbose) printf ("\n---- Application Framework Binder Normal End ------\n"); - exit (0); + exit(0); // ------------- Fatal ERROR display error and quit ------------- errorSetuid: diff --git a/src/rest-api.c b/src/rest-api.c index 437b97cf..c08d18c8 100644 --- a/src/rest-api.c +++ b/src/rest-api.c @@ -577,59 +577,105 @@ STATIC AFB_plugin ** RegisterJsonPlugins(AFB_plugin **plugins) { return (plugins); } -void initPlugins(AFB_session *session) { - static AFB_plugin **plugins; - AFB_plugin* (*pluginRegisterFct)(void); - void *plugin; - char *pluginPath; - struct dirent *pluginDir; +STATIC void scanDirectory(char *dirpath, int dirfd, AFB_plugin **plugins, int *count) { DIR *dir; - afbJsonType = json_object_new_string (AFB_MSG_JTYPE); - int num = 0; - - /* pre-allocate for 20 plugins, we will downsize if necessary */ - plugins = (AFB_plugin **) malloc (20*sizeof(AFB_plugin)); - - if ((dir = opendir(session->config->plugins)) == NULL) { - fprintf(stderr, "Could not open plugin directory [%s], exiting...\n", session->config->plugins); - exit (-1); + void *libso; + struct dirent *pluginDir; + AFB_plugin* (*pluginRegisterFct)(void); + char pluginPath[255]; + + // Open Directory to scan over it + dir = fdopendir (dirfd); + if (dir == NULL) { + fprintf(stderr, "ERROR in scanning directory\n"); + return; } + if (verbose) fprintf (stderr, "Scanning dir=[%s] for plugins\n", dirpath); while ((pluginDir = readdir(dir)) != NULL) { + + // Loop on any contained directory + if ((pluginDir->d_type == DT_DIR) && (pluginDir->d_name[0] != '.')) { + int fd = openat (dirfd, pluginDir->d_name, O_DIRECTORY); + char newpath[255]; + strncpy (newpath, dirpath, sizeof(newpath)); + strncat (newpath, "/", sizeof(newpath)); + strncat (newpath, pluginDir->d_name, sizeof(newpath)); + + scanDirectory (newpath, fd, plugins, count); + close (fd); + + } else { + + // This is a file but not a plugin let's move to next directory element + if (!strstr (pluginDir->d_name, ".so")) continue; - if (!strstr (pluginDir->d_name, ".so")) - continue; + // This is a loadable library let's check if it's a plugin + snprintf (pluginPath, sizeof(pluginPath), "%s/%s", dirpath, pluginDir->d_name); + libso = dlopen (pluginPath, RTLD_NOW | RTLD_LOCAL); - asprintf (&pluginPath, "%s/%s", session->config->plugins, pluginDir->d_name); - plugin = dlopen (pluginPath, RTLD_NOW | RTLD_LOCAL); - pluginRegisterFct = dlsym (plugin, "pluginRegister"); - free (pluginPath); - if (!plugin) { - if (verbose) fprintf(stderr, "[%s] is not loadable, continuing...\n", pluginDir->d_name); - continue; - } else if (!pluginRegisterFct) { - if (verbose) fprintf(stderr, "[%s] is not an AFB plugin, continuing...\n", pluginDir->d_name); - continue; - } + // Load fail we ignore this .so file + if (!libso) { + fprintf(stderr, "[%s] is not loadable, continuing...\n", pluginDir->d_name); + continue; + } + + pluginRegisterFct = dlsym (libso, "pluginRegister"); + free (libso); + + if (!pluginRegisterFct) { + fprintf(stderr, "[%s] is not an AFB plugin, continuing...\n", pluginDir->d_name); + continue; + } - if (verbose) fprintf(stderr, "[%s] is a valid AFB plugin, loading it\n", pluginDir->d_name); - plugins[num] = (AFB_plugin *) malloc (sizeof(AFB_plugin)); - plugins[num] = (**pluginRegisterFct)(); - num++; - /* only 20 plugins are supported at that time */ - if (num == 20) break; - } - plugins = (AFB_plugin **) realloc (plugins, (num+1)*sizeof(AFB_plugin)); - plugins[num] = NULL; + // if max plugin is reached let's stop searching + if (*count == AFB_MAX_PLUGINS) { + fprintf(stderr, "[%s] is not loaded [Max Count=%d reached]\n", *count); + continue; + } + if (verbose) fprintf(stderr, "[%s] is a valid AFB plugin, loading pos[%d]\n", pluginDir->d_name, *count); + plugins[*count] = (AFB_plugin *) malloc (sizeof(AFB_plugin)); + plugins[*count] = (**pluginRegisterFct)(); + *count = *count +1; + + } + } closedir (dir); +} + +void initPlugins(AFB_session *session) { + static AFB_plugin **plugins; + + afbJsonType = json_object_new_string (AFB_MSG_JTYPE); + int count = 0; + char *dirpath; + int dirfd; - if (plugins[0] == NULL) { + /* pre-allocate for AFB_MAX_PLUGINS plugins, we will downsize later */ + plugins = (AFB_plugin **) malloc (AFB_MAX_PLUGINS *sizeof(AFB_plugin)); + + // Loop on every directory passed in --plugins=xxx + while (dirpath = strsep(&session->config->ldpaths, ":")) { + // Ignore any directory we fail to open + if ((dirfd = open(dirpath, O_DIRECTORY)) <= 0) { + fprintf(stderr, "Invalid directory path=[%s]\n", dirpath); + continue; + } + scanDirectory (dirpath, dirfd, plugins, &count); + close (dirfd); + } + + if (count == 0) { fprintf(stderr, "No plugins found, afb-daemon is unlikely to work in this configuration, exiting...\n"); exit (-1); } + + // downsize structure to effective number of loaded plugins + plugins = (AFB_plugin **)realloc (plugins, (count+1)*sizeof(AFB_plugin)); + plugins[count] = NULL; // complete plugins and save them within current sessions session->plugins = RegisterJsonPlugins(plugins); - session->config->pluginCount = num; + session->config->pluginCount = count; } |