file: use blob_buf_free()
[project/rpcd.git] / plugin.c
index 37deddf..b75241a 100644 (file)
--- a/plugin.c
+++ b/plugin.c
@@ -1,7 +1,7 @@
 /*
 /*
- * 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
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,8 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
  * 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;
 
 
 static struct blob_buf buf;
 
@@ -94,6 +93,12 @@ rpc_plugin_call_stdout_cb(struct blob_buf *blob, char *buf, int len, void *priv)
 }
 
 static int
 }
 
 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)
 {
        struct call_context *c = priv;
 rpc_plugin_call_finish_cb(struct blob_buf *blob, int stat, void *priv)
 {
        struct call_context *c = priv;
@@ -103,12 +108,9 @@ rpc_plugin_call_finish_cb(struct blob_buf *blob, int stat, void *priv)
        {
                if (c->obj)
                {
        {
                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;
                                rv = UBUS_STATUS_OK;
-                       }
 
                        json_object_put(c->obj);
                }
 
                        json_object_put(c->obj);
                }
@@ -160,8 +162,8 @@ rpc_plugin_call(struct ubus_context *ctx, struct ubus_object *obj,
        c->argv[2] = c->method;
 
        return rpc_exec(c->argv, rpc_plugin_call_stdin_cb,
        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);
+                       rpc_plugin_call_stdout_cb, rpc_plugin_call_stderr_cb,
+                       rpc_plugin_call_finish_cb, c, ctx, req);
 
 fail:
        if (c)
 
 fail:
        if (c)
@@ -189,7 +191,7 @@ rpc_plugin_parse_signature(struct blob_attr *sig, struct ubus_method *method)
        struct blob_attr *attr;
        struct blobmsg_policy *policy = NULL;
 
        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;
                return false;
 
        n_attr = 0;
@@ -208,7 +210,7 @@ rpc_plugin_parse_signature(struct blob_attr *sig, struct ubus_method *method)
 
                blobmsg_for_each_attr(attr, sig, rem)
                {
 
                blobmsg_for_each_attr(attr, sig, rem)
                {
-                       type = blob_id(attr);
+                       type = blobmsg_type(attr);
 
                        if (type == BLOBMSG_TYPE_INT32)
                        {
 
                        if (type == BLOBMSG_TYPE_INT32)
                        {
@@ -248,7 +250,7 @@ rpc_plugin_parse_signature(struct blob_attr *sig, struct ubus_method *method)
 }
 
 static struct ubus_object *
 }
 
 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;
 {
        int len, rem, n_method;
        struct blob_attr *cur;
@@ -335,7 +337,7 @@ rpc_plugin_parse_plugin(const char *name, int fd)
 }
 
 static int
 }
 
 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];
 {
        pid_t pid;
        int rv = UBUS_STATUS_NO_DATA, fd, fds[2];
@@ -376,7 +378,7 @@ rpc_plugin_register(struct ubus_context *ctx, const char *path)
                        return UBUS_STATUS_UNKNOWN_ERROR;
 
        default:
                        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;
 
                if (!plugin)
                        goto out;
@@ -392,6 +394,37 @@ 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,
+};
+
+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;
 int rpc_plugin_api_init(struct ubus_context *ctx)
 {
        DIR *d;
@@ -400,22 +433,37 @@ int rpc_plugin_api_init(struct ubus_context *ctx)
        struct dirent *e;
        char path[PATH_MAX];
 
        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;
 
 
-       while ((e = readdir(d)) != NULL)
+                       rv |= rpc_plugin_register_exec(ctx, path);
+               }
+
+               closedir(d);
+       }
+
+       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;
 }
 
        return rv;
 }