summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--udev.c5
-rw-r--r--udev_multiplex.c34
-rw-r--r--udev_rules.c48
-rw-r--r--udev_utils.c64
-rw-r--r--udev_utils.h3
-rw-r--r--udevinfo.c2
-rw-r--r--udevstart.c2
-rw-r--r--udevtest.c11
8 files changed, 104 insertions, 65 deletions
diff --git a/udev.c b/udev.c
index 6d1d679d9a..23375b7a3e 100644
--- a/udev.c
+++ b/udev.c
@@ -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)) {