syslog: fix incorrect use of sizeof() in vsnprintf()
[project/procd.git] / hotplug.c
index ac54da4..422e849 100644 (file)
--- a/hotplug.c
+++ b/hotplug.c
@@ -66,8 +66,21 @@ static char *hotplug_msg_find_var(struct blob_attr *msg, const char *name)
        return NULL;
 }
 
+static void mkdir_p(char *dir)
+{
+       char *l = strrchr(dir, '/');
+
+       if (l) {
+               *l = '\0';
+               mkdir_p(dir);
+               *l = '/';
+               mkdir(dir, 0755);
+       }
+}
+
 static void handle_makedev(struct blob_attr *msg, struct blob_attr *data)
 {
+       unsigned int oldumask = umask(0);
        static struct blobmsg_policy mkdev_policy[2] = {
                { .type = BLOBMSG_TYPE_STRING },
                { .type = BLOBMSG_TYPE_STRING },
@@ -80,12 +93,19 @@ static void handle_makedev(struct blob_attr *msg, struct blob_attr *data)
        blobmsg_parse_array(mkdev_policy, 2, tb, blobmsg_data(data), blobmsg_data_len(data));
        if (tb[0] && tb[1] && minor && major && subsystem) {
                mode_t m = S_IFCHR;
+               char *d = strdup(blobmsg_get_string(tb[0]));
+
+               d = dirname(d);
+               mkdir_p(d);
+               free(d);
+
                if (!strcmp(subsystem, "block"))
                        m = S_IFBLK;
                mknod(blobmsg_get_string(tb[0]),
                                m | strtoul(blobmsg_data(tb[1]), NULL, 8),
                                makedev(atoi(major), atoi(minor)));
        }
+       umask(oldumask);
 }
 
 static void handle_rm(struct blob_attr *msg, struct blob_attr *data)
@@ -104,7 +124,7 @@ static void handle_exec(struct blob_attr *msg, struct blob_attr *data)
 {
        char *argv[8];
        struct blob_attr *cur;
-       int rem;
+       int rem, fd;
        int i = 0;
 
        blobmsg_for_each_attr(cur, msg, rem)
@@ -118,9 +138,14 @@ static void handle_exec(struct blob_attr *msg, struct blob_attr *data)
        }
 
        if (debug < 2) {
-               close(STDIN_FILENO);
-               close(STDOUT_FILENO);
-               close(STDERR_FILENO);
+               fd = open("/dev/null", O_RDWR);
+               if (fd > -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       dup2(fd, STDERR_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
        }
 
        if (i > 0) {
@@ -243,6 +268,7 @@ static void queue_next(void)
 
        queue_proc.pid = fork();
        if (!queue_proc.pid) {
+               uloop_done();
                c->handler(c->msg, c->data);
                exit(0);
        }
@@ -434,3 +460,9 @@ void hotplug(char *rules)
        queue_proc.cb = queue_proc_cb;
        uloop_fd_add(&hotplug_fd, ULOOP_READ);
 }
+
+void hotplug_shutdown(void)
+{
+       uloop_fd_delete(&hotplug_fd);
+       close(hotplug_fd.fd);
+}