Introduce shared object plugin api

This commit is contained in:
Jo-Philipp Wich 2013-09-02 14:52:12 +02:00
parent 0b4d4aeeac
commit 3d358bb3a1
2 changed files with 81 additions and 16 deletions

View file

@ -17,7 +17,6 @@
*/
#include "plugin.h"
#include "exec.h"
static struct blob_buf buf;
@ -254,7 +253,7 @@ rpc_plugin_parse_signature(struct blob_attr *sig, struct ubus_method *method)
}
static struct ubus_object *
rpc_plugin_parse_plugin(const char *name, int fd)
rpc_plugin_parse_exec(const char *name, int fd)
{
int len, rem, n_method;
struct blob_attr *cur;
@ -341,7 +340,7 @@ rpc_plugin_parse_plugin(const char *name, int fd)
}
static int
rpc_plugin_register(struct ubus_context *ctx, const char *path)
rpc_plugin_register_exec(struct ubus_context *ctx, const char *path)
{
pid_t pid;
int rv = UBUS_STATUS_NO_DATA, fd, fds[2];
@ -382,7 +381,7 @@ rpc_plugin_register(struct ubus_context *ctx, const char *path)
return UBUS_STATUS_UNKNOWN_ERROR;
default:
plugin = rpc_plugin_parse_plugin(name + 1, fds[0]);
plugin = rpc_plugin_parse_exec(name + 1, fds[0]);
if (!plugin)
goto out;
@ -398,6 +397,35 @@ out:
}
}
static LIST_HEAD(plugins);
static const struct rpc_daemon_ops ops = {
.access = rpc_session_access,
.exec = rpc_exec,
};
static int
rpc_plugin_register_library(struct ubus_context *ctx, const char *path)
{
struct rpc_plugin *p;
void *dlh;
dlh = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
if (!dlh)
return UBUS_STATUS_UNKNOWN_ERROR;
p = dlsym(dlh, "rpc_plugin");
if (!p)
return UBUS_STATUS_NOT_FOUND;
list_add(&p->list, &plugins);
return p->init(&ops, ctx);
}
int rpc_plugin_api_init(struct ubus_context *ctx)
{
DIR *d;
@ -406,22 +434,37 @@ int rpc_plugin_api_init(struct ubus_context *ctx)
struct dirent *e;
char path[PATH_MAX];
d = opendir(RPC_PLUGIN_DIRECTORY);
if (!d)
return UBUS_STATUS_NOT_FOUND;
if ((d = opendir(RPC_PLUGIN_DIRECTORY)) != NULL)
{
while ((e = readdir(d)) != NULL)
{
snprintf(path, sizeof(path) - 1, RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
snprintf(path, sizeof(path) - 1,
RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR))
continue;
rv |= rpc_plugin_register(ctx, path);
rv |= rpc_plugin_register_exec(ctx, path);
}
closedir(d);
}
if ((d = opendir(RPC_LIBRARY_DIRECTORY)) != NULL)
{
while ((e = readdir(d)) != NULL)
{
snprintf(path, sizeof(path) - 1,
RPC_LIBRARY_DIRECTORY "/%s", e->d_name);
if (stat(path, &s) || !S_ISREG(s.st_mode))
continue;
rv |= rpc_plugin_register_library(ctx, path);
}
closedir(d);
}
return rv;
}

View file

@ -21,6 +21,7 @@
#define _GNU_SOURCE /* asprintf() */
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
@ -33,8 +34,29 @@
#include <libubox/blobmsg_json.h>
#include <libubus.h>
#include "exec.h"
#include "session.h"
/* location of plugin executables */
#define RPC_PLUGIN_DIRECTORY "/usr/lib/luci-rpcd/plugins"
#define RPC_PLUGIN_DIRECTORY "/usr/libexec/luci-rpcd"
/* location of plugin libraries */
#define RPC_LIBRARY_DIRECTORY "/usr/lib/luci-rpcd"
struct rpc_daemon_ops {
bool (*access)(const char *sid, const char *scope,
const char *object, const char *function);
int (*exec)(const char **args,
rpc_exec_write_cb_t in, rpc_exec_read_cb_t out,
rpc_exec_read_cb_t err, rpc_exec_done_cb_t end,
void *priv, struct ubus_context *ctx,
struct ubus_request_data *req);
};
struct rpc_plugin {
struct list_head list;
int (*init)(const struct rpc_daemon_ops *ops, struct ubus_context *ctx);
};
int rpc_plugin_api_init(struct ubus_context *ctx);