diff options
-rw-r--r-- | udev.c | 5 | ||||
-rw-r--r-- | udev_multiplex.c | 34 | ||||
-rw-r--r-- | udev_rules.c | 48 | ||||
-rw-r--r-- | udev_utils.c | 64 | ||||
-rw-r--r-- | udev_utils.h | 3 | ||||
-rw-r--r-- | udevinfo.c | 2 | ||||
-rw-r--r-- | udevstart.c | 2 | ||||
-rw-r--r-- | udevtest.c | 11 |
8 files changed, 104 insertions, 65 deletions
@@ -141,7 +141,7 @@ int main(int argc, char *argv[], char *envp[]) if (!subsystem && argc == 2) subsystem = argv[1]; - udev_init_device(&udev, devpath, subsystem); + udev_init_device(&udev, devpath, subsystem, action); if (!action || !subsystem || !devpath) { err("action, subsystem or devpath missing"); @@ -230,10 +230,11 @@ int main(int argc, char *argv[], char *envp[]) } hotplug: - udev_cleanup_device(&udev); if (udev_hotplug_d && managed_event) udev_multiplex_directory(&udev, HOTPLUGD_DIR, HOTPLUG_SUFFIX); + udev_cleanup_device(&udev); + logging_close(); return retval; } diff --git a/udev_multiplex.c b/udev_multiplex.c index 9ab11e6bea..22bbaf7b61 100644 --- a/udev_multiplex.c +++ b/udev_multiplex.c @@ -32,38 +32,6 @@ #include "udev_utils.h" #include "logging.h" -static int run_program(struct udevice *udev, const char *filename) -{ - pid_t pid; - int fd; - - dbg("running %s", filename); - - pid = fork(); - switch (pid) { - case 0: - /* child */ - fd = open("/dev/null", O_RDWR); - if ( fd >= 0) { - dup2(fd, STDOUT_FILENO); - dup2(fd, STDIN_FILENO); - dup2(fd, STDERR_FILENO); - } - close(fd); - - execl(filename, filename, udev->subsystem, NULL); - dbg("exec of child failed"); - _exit(1); - case -1: - dbg("fork of child failed"); - break; - return -1; - default: - waitpid(pid, NULL, 0); - } - - return 0; -} /* * runs files in these directories in order: @@ -117,7 +85,7 @@ void udev_multiplex_directory(struct udevice *udev, const char *basedir, const c add_matching_files(&name_list, dirname, suffix); list_for_each_entry_safe(name_loop, name_tmp, &name_list, node) { - run_program(udev, name_loop->name); + execute_command(name_loop->name, udev->subsystem); list_del(&name_loop->node); } diff --git a/udev_rules.c b/udev_rules.c index 2b5c411d96..069dec7d04 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -31,7 +31,6 @@ #include <unistd.h> #include <errno.h> #include <sys/wait.h> -#include <sys/stat.h> #include "libsysfs/sysfs/libsysfs.h" #include "list.h" @@ -327,7 +326,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize, struct udevice udev_parent; dbg("found parent '%s', get the node name", class_dev_parent->path); - udev_init_device(&udev_parent, NULL, NULL); + udev_init_device(&udev_parent, NULL, NULL, NULL); /* lookup the name in the udev_db with the DEVPATH of the parent */ if (udev_db_get_device(&udev_parent, &class_dev_parent->path[strlen(sysfs_path)]) == 0) { strlcat(string, udev_parent.name, maxsize); @@ -364,21 +363,22 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize, } } -static int execute_program(struct udevice *udev, const char *path, char *value, int len) +static int execute_program_pipe(const char *command, const char *subsystem, char *value, int len) { int retval; int count; int status; - int fds[2]; + int pipefds[2]; pid_t pid; char *pos; char arg[PATH_SIZE]; char *argv[(sizeof(arg) / 2) + 1]; + int devnull; int i; - strlcpy(arg, path, sizeof(arg)); + strlcpy(arg, command, sizeof(arg)); i = 0; - if (strchr(path, ' ')) { + if (strchr(arg, ' ')) { pos = arg; while (pos != NULL) { if (pos[0] == '\'') { @@ -397,12 +397,12 @@ static int execute_program(struct udevice *udev, const char *path, char *value, dbg("execute '%s' with parsed arguments", arg); } else { argv[0] = arg; - argv[1] = udev->subsystem; + argv[1] = (char *) subsystem; argv[2] = NULL; dbg("execute '%s' with subsystem '%s' argument", arg, argv[1]); } - retval = pipe(fds); + retval = pipe(pipefds); if (retval != 0) { err("pipe failed"); return -1; @@ -412,22 +412,27 @@ static int execute_program(struct udevice *udev, const char *path, char *value, switch(pid) { case 0: /* child dup2 write side of pipe to STDOUT */ - dup2(fds[1], STDOUT_FILENO); + devnull = open("/dev/null", O_RDWR); + if (devnull >= 0) { + dup2(devnull, STDIN_FILENO); + dup2(devnull, STDERR_FILENO); + close(devnull); + } + dup2(pipefds[1], STDOUT_FILENO); retval = execv(arg, argv); - err("exec of program failed"); _exit(1); case -1: - err("fork of '%s' failed", path); + err("fork of '%s' failed", arg); retval = -1; break; default: - /* parent reads from fds[0] */ - close(fds[1]); + /* parent reads from pipefds[0] */ + close(pipefds[1]); retval = 0; i = 0; while (1) { - count = read(fds[0], value + i, len - i-1); + count = read(pipefds[0], value + i, len - i-1); if (count < 0) { err("read failed with '%s'", strerror(errno)); retval = -1; @@ -445,7 +450,7 @@ static int execute_program(struct udevice *udev, const char *path, char *value, } value[i] = '\0'; - close(fds[0]); + close(pipefds[0]); waitpid(pid, &status, 0); if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { @@ -470,9 +475,9 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, struct sysfs_device *parent_device = sysfs_device; if (rule->kernel_operation != KEY_OP_UNSET) { - dbg("check for " KEY_KERNEL " rule->kernel='%s' class_dev->name='%s'", - rule->kernel, class_dev->name); - if (strcmp_pattern(rule->kernel, class_dev->name) != 0) { + dbg("check for " KEY_KERNEL " rule->kernel='%s' udev_kernel_name='%s'", + rule->kernel, udev->kernel_name); + if (strcmp_pattern(rule->kernel, udev->kernel_name) != 0) { dbg(KEY_KERNEL " is not matching"); if (rule->kernel_operation != KEY_OP_NOMATCH) goto exit; @@ -485,8 +490,8 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, } if (rule->subsystem_operation != KEY_OP_UNSET) { - dbg("check for " KEY_SUBSYSTEM " rule->subsystem='%s' class_dev->name='%s'", - rule->subsystem, class_dev->name); + dbg("check for " KEY_SUBSYSTEM " rule->subsystem='%s' udev->subsystem='%s'", + rule->subsystem, udev->subsystem); if (strcmp_pattern(rule->subsystem, udev->subsystem) != 0) { dbg(KEY_SUBSYSTEM " is not matching"); if (rule->subsystem_operation != KEY_OP_NOMATCH) @@ -642,7 +647,8 @@ try_parent: dbg("check " KEY_PROGRAM); strlcpy(program, rule->program, sizeof(program)); apply_format(udev, program, sizeof(program), class_dev, sysfs_device); - if (execute_program(udev, program, udev->program_result, sizeof(udev->program_result)) != 0) { + if (execute_program_pipe(program, udev->subsystem, + udev->program_result, sizeof(udev->program_result)) != 0) { dbg(KEY_PROGRAM " returned nonzero"); if (rule->program_operation != KEY_OP_NOMATCH) goto exit; diff --git a/udev_utils.c b/udev_utils.c index 37607492ac..4695ef0d72 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -27,6 +27,7 @@ #include <errno.h> #include <ctype.h> #include <dirent.h> +#include <sys/wait.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/utsname.h> @@ -38,7 +39,7 @@ #include "list.h" -int udev_init_device(struct udevice *udev, const char* devpath, const char *subsystem) +int udev_init_device(struct udevice *udev, const char* devpath, const char *subsystem, const char *action) { char *pos; @@ -317,3 +318,64 @@ int add_matching_files(struct list_head *name_list, const char *dirname, const c closedir(dir); return 0; } + +int execute_command(const char *command, const char *subsystem) +{ + int retval; + pid_t pid; + char arg[PATH_SIZE]; + char *argv[(PATH_SIZE / 2) + 1]; + char *pos; + int devnull; + int i; + + strlcpy(arg, command, sizeof(arg)); + i = 0; + if (strchr(arg, ' ')) { + pos = arg; + while (pos != NULL) { + if (pos[0] == '\'') { + /* don't separate if in apostrophes */ + pos++; + argv[i] = strsep(&pos, "\'"); + while (pos && pos[0] == ' ') + pos++; + } else { + argv[i] = strsep(&pos, " "); + } + dbg("arg[%i] '%s'", i, argv[i]); + i++; + } + argv[i] = NULL; + dbg("execute '%s' with parsed arguments", arg); + } else { + argv[0] = arg; + argv[1] = (char *) subsystem; + argv[2] = NULL; + dbg("execute '%s' with subsystem '%s' argument", arg, argv[1]); + } + + pid = fork(); + switch (pid) { + case 0: + /* child */ + devnull = open("/dev/null", O_RDWR); + if (devnull >= 0) { + dup2(devnull, STDIN_FILENO); + dup2(devnull, STDOUT_FILENO); + dup2(devnull, STDERR_FILENO); + close(devnull); + } + retval = execv(arg, argv); + err("exec of child failed"); + _exit(1); + case -1: + dbg("fork of child failed"); + break; + return -1; + default: + waitpid(pid, NULL, 0); + } + + return 0; +} diff --git a/udev_utils.h b/udev_utils.h index 5ebc9e5bb6..9cdae6db57 100644 --- a/udev_utils.h +++ b/udev_utils.h @@ -29,7 +29,7 @@ struct name_entry { char name[PATH_SIZE]; }; -extern int udev_init_device(struct udevice *udev, const char* devpath, const char *subsystem); +extern int udev_init_device(struct udevice *udev, const char* devpath, const char *subsystem, const char *action); extern void udev_cleanup_device(struct udevice *udev); extern int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel); @@ -43,5 +43,6 @@ extern void remove_trailing_char(char *path, char c); extern void replace_untrusted_chars(char *string); extern int name_list_add(struct list_head *name_list, const char *name, int sort); extern int add_matching_files(struct list_head *name_list, const char *dirname, const char *suffix); +extern int execute_command(const char *command, const char *subsystem); #endif diff --git a/udevinfo.c b/udevinfo.c index 788dd519a8..31e719fe35 100644 --- a/udevinfo.c +++ b/udevinfo.c @@ -199,7 +199,7 @@ int main(int argc, char *argv[], char *envp[]) logging_init("udevinfo"); udev_init_config(); - udev_init_device(&udev, NULL, NULL); + udev_init_device(&udev, NULL, NULL, NULL); /* get command line options */ while (1) { diff --git a/udevstart.c b/udevstart.c index a862dadf88..4bd4795874 100644 --- a/udevstart.c +++ b/udevstart.c @@ -123,7 +123,7 @@ static int add_device(const char *path, const char *subsystem) return -ENODEV; } - udev_init_device(&udev, devpath, subsystem); + udev_init_device(&udev, devpath, subsystem, "add"); udev_add_device(&udev, class_dev); /* run dev.d/ scripts if we created a node or changed a netif name */ diff --git a/udevtest.c b/udevtest.c index f0c38b3a51..2caa654d4c 100644 --- a/udevtest.c +++ b/udevtest.c @@ -86,16 +86,17 @@ int main(int argc, char *argv[], char *envp[]) } else devpath = argv[1]; - info("looking at '%s'", devpath); + subsystem = argv[2]; + setenv("DEVPATH", devpath, 1); + setenv("SUBSYSTEM", subsystem, 1); + setenv("ACTION", "add", 1); + info("looking at device '%s' from subsystem '%s'", devpath, subsystem); /* initialize the naming deamon */ udev_rules_init(); - if (argc == 3) - subsystem = argv[2]; - /* fill in values and test_run flag*/ - udev_init_device(&udev, devpath, subsystem); + udev_init_device(&udev, devpath, subsystem, "add"); /* skip subsystems without "dev", but handle net devices */ if (udev.type != DEV_NET && subsystem_expect_no_dev(udev.subsystem)) { |