procd: support relayoing daemon stdout/stderr to syslog
[project/procd.git] / plug / hotplug.c
index ca1e823..061833a 100644 (file)
@@ -22,6 +22,7 @@
 #include <libubox/blobmsg_json.h>
 #include <libubox/json_script.h>
 #include <libubox/uloop.h>
+#include <json/json.h>
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -161,10 +162,10 @@ static void handle_firmware(struct blob_attr *msg, struct blob_attr *data)
        char *dir = blobmsg_get_string(blobmsg_data(data));
        char *file = hotplug_msg_find_var(msg, "FIRMWARE");
        char *dev = hotplug_msg_find_var(msg, "DEVPATH");
-       void *fw_data;
-       struct stat s;
+       struct stat s = { 0 };
        char *path, loadpath[256], syspath[256];
-       int fw, load, sys, len;
+       int fw, src, load, len;
+       static char buf[4096];
 
        DEBUG(2, "Firmware request for %s/%s\n", dir, file);
 
@@ -173,35 +174,24 @@ static void handle_firmware(struct blob_attr *msg, struct blob_attr *data)
                exit(-1);
        }
 
-       path = malloc(strlen(dir) + strlen(file) + 2);
-       if (!path) {
-               ERROR("Failed to allocate memory\n");
-               exit(-1);
-       }
+       path = alloca(strlen(dir) + strlen(file) + 2);
        sprintf(path, "%s/%s", dir, file);
 
        if (stat(path, &s)) {
                ERROR("Could not find firmware %s\n", path);
-               exit(-1);
+               src = -1;
+               s.st_size = 0;
+               goto send_to_kernel;
        }
 
-       fw_data = malloc(s.st_size);
-       if (!fw_data) {
-               ERROR("Failed to allocate firmware data memory\n");
-               exit(-1);
-       }
-
-       fw = open(path, O_RDONLY);
-       if (!fw) {
+       src = open(path, O_RDONLY);
+       if (src < 0) {
                ERROR("Failed to open %s\n", path);
-               exit(-1);
+               s.st_size = 0;
+               goto send_to_kernel;
        }
-       if (read(fw, fw_data, s.st_size) != s.st_size) {
-               ERROR("Failed to read firmware data\n");
-               exit(-1);
-       }
-       close(fw);
 
+send_to_kernel:
        snprintf(loadpath, sizeof(loadpath), "/sys/%s/loading", dev);
        load = open(loadpath, O_WRONLY);
        if (!load) {
@@ -212,19 +202,23 @@ static void handle_firmware(struct blob_attr *msg, struct blob_attr *data)
        close(load);
 
        snprintf(syspath, sizeof(syspath), "/sys/%s/data", dev);
-       sys = open(syspath, O_WRONLY);
-       if (!sys) {
+       fw = open(syspath, O_WRONLY);
+       if (fw < 0) {
                ERROR("Failed to open %s\n", syspath);
                exit(-1);
        }
 
        len = s.st_size;
-       while (len > 4096) {
-               write(fw, fw_data, 4096);
-               len -= 4096;
+       while (len) {
+               len = read(src, buf, sizeof(buf));
+               if (len <= 0)
+                       break;
+
+               write(fw, buf, len);
        }
-       if (len)
-               write(fw, fw_data, len);
+
+       if (src >= 0)
+               close(src);
        close(fw);
 
        load = open(loadpath, O_WRONLY);
@@ -342,7 +336,7 @@ rule_handle_file(struct json_script_ctx *ctx, const char *name)
        json_object *obj;
 
        obj = json_object_from_file((char*)name);
-       if (is_error(obj))
+       if (!obj)
                return NULL;
 
        blob_buf_init(&script, 0);
@@ -399,6 +393,18 @@ static struct json_script_ctx jctx = {
        .handle_file = rule_handle_file,
 };
 
+static void hotplug_handler_debug(struct blob_attr *data)
+{
+       char *str;
+
+       if (debug < 3)
+               return;
+
+       str = blobmsg_format_json(data, true);
+       DEBUG(3, "%s\n", str);
+       free(str);
+}
+
 static void hotplug_handler(struct uloop_fd *u, unsigned int ev)
 {
        int i = 0;
@@ -421,7 +427,7 @@ static void hotplug_handler(struct uloop_fd *u, unsigned int ev)
                i += l;
        }
        blobmsg_close_table(&b, index);
-       DEBUG(3, "%s\n", blobmsg_format_json(b.head, true));
+       hotplug_handler_debug(b.head);
        json_script_run(&jctx, rule_file, blob_data(b.head));
 }
 
@@ -441,6 +447,7 @@ void hotplug_last_event(uloop_timeout_handler handler)
 void hotplug(char *rules)
 {
        struct sockaddr_nl nls;
+       int nlbufsize = 512 * 1024;
 
        rule_file = strdup(rules);
        memset(&nls,0,sizeof(struct sockaddr_nl));
@@ -457,6 +464,9 @@ void hotplug(char *rules)
                exit(1);
        }
 
+       if (setsockopt(hotplug_fd.fd, SOL_SOCKET, SO_RCVBUFFORCE, &nlbufsize, sizeof(nlbufsize)))
+               ERROR("Failed to resize receive buffer: %s\n", strerror(errno));
+
        json_script_init(&jctx);
        queue_proc.cb = queue_proc_cb;
        uloop_fd_add(&hotplug_fd, ULOOP_READ);