diff --git a/udev.c b/udev.c index 4096b8b348..2a6e1efc99 100644 --- 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); diff --git a/udev_utils.c b/udev_utils.c index 2524baf592..fd4cd13e5d 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -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) { diff --git a/udev_utils.h b/udev_utils.h index 5f4152df82..5b223855b6 100644 --- a/udev_utils.h +++ b/udev_utils.h @@ -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); diff --git a/udevsend.c b/udevsend.c index 94ab6ff625..0ba1b58a4b 100644 --- a/udevsend.c +++ b/udevsend.c @@ -19,17 +19,17 @@ * */ +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include #include "udev.h" diff --git a/udevstart.c b/udevstart.c index 0bcbc39737..5f3ba711f0 100644 --- a/udevstart.c +++ b/udevstart.c @@ -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);