chiark / gitweb /
allow RUN to send the environment to a local socket
authorKay Sievers <kay.sievers@suse.de>
Mon, 1 Aug 2005 03:07:19 +0000 (05:07 +0200)
committerKay Sievers <kay.sievers@suse.de>
Mon, 1 Aug 2005 03:07:19 +0000 (05:07 +0200)
RUN="socket:<name>" will send the environment in the kernel uevent
format to the named destination. Using the socket instead of the program
to pass the hotplug events to the HAL daemon, cuts down the running
time of udevstart from 0.8 to 0.4 seconds on my box.

  env -i ACTION=add DEVPATH=/block/hda/hda1 strace -s10000 ./udev block
  sendto(3, "add@/block/hda/hda1\0
    ACTION=add\0DEVPATH=/block/hda/hda1\0UDEV_LOG=3\0
    ID_TYPE=disk\0ID_MODEL=HTS726060M9AT00\0ID_SERIAL=MRH401M4G6UM9B\0
    ID_REVISION=MH4OA6BA\0ID_BUS=ata\0ID_PATH=pci-0000:00:1f.1-ide-0:0\0
    ID_FS_USAGE=other\0ID_FS_TYPE=swap\0ID_FS_VERSION=2\0
    ID_FS_UUID=9352cfef-7687-47bc-a2a3-34cf136f72e1\0
    ID_FS_LABEL=ThisIsSwap\0ID_FS_LABEL_SAFE=ThisIsSwap\0
    DEVNAME=/dev/hda1\0"

Signed-off-by: Kay Sievers <kay.sievers@suse.de>
udev.c
udev_utils.c
udev_utils.h
udevsend.c
udevstart.c

diff --git a/udev.c b/udev.c
index 4096b8b3485bdf53dd439bc80e5f0fa506c36160..2a6e1efc9932e1699b9f0b69e3b2222a12f8a9a0 100644 (file)
--- a/udev.c
+++ b/udev.c
@@ -123,8 +123,12 @@ int main(int argc, char *argv[], char *envp[])
                struct name_entry *name_loop;
 
                dbg("executing run list");
-               list_for_each_entry(name_loop, &udev.run_list, node)
-                       execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+               list_for_each_entry(name_loop, &udev.run_list, node) {
+                       if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+                               pass_env_to_socket(&name_loop->name[strlen("socket:")], devpath, action);
+                       else
+                               execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+               }
        }
 
        udev_cleanup_device(&udev);
index 2524baf5928664ae2e0968cc752c56a1057e7280..fd4cd13e5d6cfe24cae0499f10bcc7060d52dddb 100644 (file)
@@ -28,6 +28,8 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <syslog.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
@@ -372,6 +374,38 @@ int add_matching_files(struct list_head *name_list, const char *dirname, const c
        return 0;
 }
 
+int pass_env_to_socket(const char *sockname, const char *devpath, const char *action)
+{
+       int sock;
+       struct sockaddr_un saddr;
+       socklen_t addrlen;
+       char buf[2048];
+       size_t bufpos = 0;
+       int i;
+       int retval;
+
+       dbg("pass environment to socket '%s'", sockname);
+       sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+       memset(&saddr, 0x00, sizeof(struct sockaddr_un));
+       saddr.sun_family = AF_LOCAL;
+       /* only abstract namespace is supported */
+       strcpy(&saddr.sun_path[1], sockname);
+       addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
+
+       bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath);
+       bufpos++;
+       for (i = 0; environ[i] != NULL && bufpos < sizeof(buf); i++) {
+               bufpos += strlcpy(&buf[bufpos], environ[i], sizeof(buf) - bufpos-1);
+               bufpos++;
+       }
+
+       retval = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, addrlen);
+       if (retval != -1)
+               retval = 0;
+
+       return retval;
+}
+
 int execute_program(const char *command, const char *subsystem,
                    char *result, size_t ressize, size_t *reslen)
 {
index 5f4152df829da95b7b9f0ba65258097f0b93783a..5b223855b6a735d23e883e9af2ef23ee948cc884 100644 (file)
@@ -44,6 +44,7 @@ extern void replace_untrusted_chars(char *string);
 extern int name_list_add(struct list_head *name_list, const char *name, int sort);
 extern int name_list_key_add(struct list_head *name_list, const char *key, const char *value);
 extern int add_matching_files(struct list_head *name_list, const char *dirname, const char *suffix);
+extern int pass_env_to_socket(const char *name, const char *devpath, const char *action);
 extern int execute_program(const char *command, const char *subsystem,
                           char *result, size_t ressize, size_t *reslen);
 
index 94ab6ff6257699a11eb4474322cd8f27e04d24ea..0ba1b58a4ba380a49095d0fa4e7f1822c996b6ad 100644 (file)
  *
  */
 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/un.h>
-#include <time.h>
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include <string.h>
 #include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/un.h>
 #include <linux/stddef.h>
 
 #include "udev.h"
index 0bcbc3973723d605987c31c44b1d8a1903dd0e5e..5f3ba711f0303deffaa1a5dc160ecdbd9d114597 100644 (file)
@@ -160,8 +160,12 @@ run:
                struct name_entry *name_loop;
 
                dbg("executing run list");
-               list_for_each_entry(name_loop, &udev.run_list, node)
-                       execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+               list_for_each_entry(name_loop, &udev.run_list, node) {
+                       if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+                               pass_env_to_socket(&name_loop->name[strlen("socket:")], devpath, "add");
+                       else
+                               execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+               }
        }
 exit:
        sysfs_close_class_device(class_dev);