Trigger events for devices with a matching sysfs attribute\. If a value is specified along with the attribute name, the content of the attribute is matched against the given value using shell style pattern matching\. If no value is specified, the existence of the sysfs attribute is checked\. This option can be specified multiple times\.
.RE
.PP
-\fB\-\-attr\-nomatch\fR\fB\fIattribute=value\fR\fR
+\fB\-\-attr\-nomatch=\fR\fB\fIattribute=value\fR\fR
.RS 4
Do not trigger events for devices with a matching sysfs attribute\. If a value is specified along with the attribute name, the content of the attribute is matched against the given value using shell style pattern matching\. If no value is specified, the existence of the sysfs attribute is checked\. This option can be specified multiple times\.
.RE
.PP
-\fB\-\-socket\fR\fB\fIpath\fR\fR
+\fB\-\-socket=\fR\fB\fIpath\fR\fR
.RS 4
Pass the synthesized events to the specified socket, instead of triggering a global kernel event\. All available event values will be send in the same format the kernel sends an uevent, or
\fBRUN+="socket:\fR\fB\fIpath\fR\fR\fB"\fR
sends a message\. If the first character of the specified path is an @ character, an abstract namespace socket is used, instead of an existing socket file\.
.RE
+.PP
+\fB\-\-env=\fR\fB\fIKEY\fR\fR\fB=\fR\fB\fIvalue\fR\fR
+.RS 4
+Pass an additional environemt key to the event\. This works only with the \-\-socket option\.
+.RE
.SS "udevadm settle [options]"
.PP
Watches the udev event queue, and exits if all current events are handled\.
close(fd);
}
-static int pass_to_socket(const char *devpath, const char *action)
+static int pass_to_socket(const char *devpath, const char *action, const char *env)
{
struct udevice udev;
struct name_entry *name_loop;
bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath);
bufpos++;
+ /* add cookie */
+ if (env != NULL) {
+ bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "%s", env);
+ bufpos++;
+ }
+
/* add standard keys */
bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "DEVPATH=%s", devpath);
bufpos++;
return err;
}
-static void exec_list(const char *action)
+static void exec_list(const char *action, const char *env)
{
struct name_entry *loop_device;
struct name_entry *tmp_device;
if (delay_device(loop_device->name))
continue;
if (sock >= 0)
- pass_to_socket(loop_device->name, action);
+ pass_to_socket(loop_device->name, action, env);
else
trigger_uevent(loop_device->name, action);
list_del(&loop_device->node);
/* trigger remaining delayed devices */
list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) {
if (sock >= 0)
- pass_to_socket(loop_device->name, action);
+ pass_to_socket(loop_device->name, action, env);
else
trigger_uevent(loop_device->name, action);
list_del(&loop_device->node);
const char *sockpath = NULL;
int option;
const char *action = "add";
+ const char *env = NULL;
static const struct option options[] = {
{ "verbose", 0, NULL, 'v' },
{ "dry-run", 0, NULL, 'n' },
{ "subsystem-nomatch", 1, NULL, 'S' },
{ "attr-match", 1, NULL, 'a' },
{ "attr-nomatch", 1, NULL, 'A' },
+ { "env", 1, NULL, 'e' },
{}
};
sysfs_init();
while (1) {
- option = getopt_long(argc, argv, "vnFo:hc:s:S:a:A:", options, NULL);
+ option = getopt_long(argc, argv, "vnFo:hce::s:S:a:A:", options, NULL);
if (option == -1)
break;
case 'c':
action = optarg;
break;
+ case 'e':
+ if (strchr(optarg, '=') != NULL)
+ env = optarg;
+ break;
case 's':
name_list_add(&filter_subsystem_match_list, optarg, 0);
break;
" --dry-run do not actually trigger the events\n"
" --retry-failed trigger only the events which have been\n"
" marked as failed during a previous run\n"
+ " --socket=<socket path> pass events to socket instead of triggering kernel events\n"
+ " --env=<KEY>=<value> pass an additional key (works only with --socket=)\n"
" --subsystem-match=<subsystem> trigger devices from a matching subystem\n"
" --subsystem-nomatch=<subsystem> exclude devices from a matching subystem\n"
" --attr-match=<file[=<value>]> trigger devices with a matching sysfs\n"
strlcpy(&saddr.sun_path[1], sockpath, sizeof(saddr.sun_path)-1);
saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]);
}
+ } else if (env != NULL) {
+ fprintf(stderr, "error: --env= only valid with --socket= option\n");
+ goto exit;
}
if (failed) {
scan_failed();
- exec_list(action);
+ exec_list(action, env);
} else {
char base[PATH_SIZE];
struct stat statbuf;
strlcat(base, "/subsystem", sizeof(base));
if (stat(base, &statbuf) == 0) {
scan_subsystem("subsystem", SCAN_SUBSYSTEM);
- exec_list(action);
+ exec_list(action, env);
scan_subsystem("subsystem", SCAN_DEVICES);
- exec_list(action);
+ exec_list(action, env);
} else {
scan_subsystem("bus", SCAN_SUBSYSTEM);
- exec_list(action);
+ exec_list(action, env);
scan_subsystem("bus", SCAN_DEVICES);
scan_class();
strlcat(base, "/class/block", sizeof(base));
if (stat(base, &statbuf) != 0)
scan_block();
- exec_list(action);
+ exec_list(action, env);
}
}