/*
- * luci-rpcd - LuCI UBUS RPC server
+ * rpcd - UBUS RPC server
*
- * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
+ * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "plugin.h"
-#include "exec.h"
+#include <rpcd/plugin.h>
static struct blob_buf buf;
return len;
}
+static int
+rpc_plugin_call_stderr_cb(struct blob_buf *blob, char *buf, int len, void *priv)
+{
+ return len;
+}
+
static int
rpc_plugin_call_finish_cb(struct blob_buf *blob, int stat, void *priv)
{
{
if (c->obj)
{
- if (json_object_get_type(c->obj) == json_type_object ||
- json_object_get_type(c->obj) == json_type_array)
- {
- blobmsg_add_json_element(blob, NULL, c->obj);
+ if (json_object_get_type(c->obj) == json_type_object &&
+ blobmsg_add_object(blob, c->obj))
rv = UBUS_STATUS_OK;
- }
json_object_put(c->obj);
}
{
int rv = UBUS_STATUS_UNKNOWN_ERROR;
struct call_context *c;
- char *plugin;
+ char *plugin, *mptr;
- c = calloc(1, sizeof(*c));
+ c = calloc_a(sizeof(*c), &mptr, strlen(method) + 1);
if (!c)
goto fail;
- c->method = strdup(method);
+ c->method = strcpy(mptr, method);
c->input = blobmsg_format_json(msg, true);
c->tok = json_tokener_new();
- if (!c->method || !c->input || !c->tok)
+ if (!c->input || !c->tok)
goto fail;
plugin = c->path + sprintf(c->path, "%s/", RPC_PLUGIN_DIRECTORY);
c->argv[1] = "call";
c->argv[2] = c->method;
- return rpc_exec(c->argv, rpc_plugin_call_stdin_cb,
- rpc_plugin_call_stdout_cb, NULL, rpc_plugin_call_finish_cb,
- c, ctx, req);
+ rv = rpc_exec(c->argv, rpc_plugin_call_stdin_cb,
+ rpc_plugin_call_stdout_cb, rpc_plugin_call_stderr_cb,
+ rpc_plugin_call_finish_cb, c, ctx, req);
+
+ if (rv == UBUS_STATUS_OK)
+ return rv;
fail:
if (c)
{
- if (c->method)
- free(c->method);
-
if (c->input)
free(c->input);
struct blob_attr *attr;
struct blobmsg_policy *policy = NULL;
- if (!sig || blob_id(sig) != BLOBMSG_TYPE_TABLE)
+ if (!sig || blobmsg_type(sig) != BLOBMSG_TYPE_TABLE)
return false;
n_attr = 0;
blobmsg_for_each_attr(attr, sig, rem)
{
- type = blob_id(attr);
+ type = blobmsg_type(attr);
if (type == BLOBMSG_TYPE_INT32)
{
}
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;
obj_type = calloc(1, sizeof(*obj_type));
- if (!obj_type)
+ if (!obj_type) {
+ free(obj);
return NULL;
+ }
+
+ if (asprintf((char **)&obj_type->name, "luci-rpc-plugin-%s", name) < 0) {
+ free(obj);
+ free(obj_type);
+ return NULL;
+ }
- asprintf((char **)&obj_type->name, "luci-rpc-plugin-%s", name);
obj_type->methods = methods;
obj_type->n_methods = n_method;
}
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];
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;
}
}
+
+static LIST_HEAD(plugins);
+
+static const struct rpc_daemon_ops ops = {
+ .session_access = rpc_session_access,
+ .session_create_cb = rpc_session_create_cb,
+ .session_destroy_cb = rpc_session_destroy_cb,
+ .exec = rpc_exec,
+ .exec_timeout = &rpc_exec_timeout,
+};
+
+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_LOCAL);
+
+ 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;
struct dirent *e;
char path[PATH_MAX];
- d = opendir(RPC_PLUGIN_DIRECTORY);
+ if ((d = opendir(RPC_PLUGIN_DIRECTORY)) != NULL)
+ {
+ while ((e = readdir(d)) != NULL)
+ {
+ snprintf(path, sizeof(path) - 1,
+ RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
- if (!d)
- return UBUS_STATUS_NOT_FOUND;
+ if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR))
+ continue;
+
+ rv |= rpc_plugin_register_exec(ctx, path);
+ }
+
+ closedir(d);
+ }
- while ((e = readdir(d)) != NULL)
+ if ((d = opendir(RPC_LIBRARY_DIRECTORY)) != NULL)
{
- snprintf(path, sizeof(path) - 1, RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
+ 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) || !(s.st_mode & S_IXUSR))
- continue;
+ if (stat(path, &s) || !S_ISREG(s.st_mode))
+ continue;
- rv |= rpc_plugin_register(ctx, path);
- }
+ rv |= rpc_plugin_register_library(ctx, path);
+ }
- closedir(d);
+ closedir(d);
+ }
return rv;
}