1 /* SPDX-License-Identifier: GPL-2.0+ */
14 #include "alloc-util.h"
15 #include "device-private.h"
16 #include "device-util.h"
18 #include "format-util.h"
19 #include "libudev-util.h"
20 #include "netlink-util.h"
21 #include "path-util.h"
22 #include "process-util.h"
23 #include "signal-util.h"
24 #include "stdio-util.h"
25 #include "string-util.h"
28 #include "udev-builtin.h"
29 #include "udev-node.h"
30 #include "udev-watch.h"
33 typedef struct Spawn
{
36 usec_t timeout_warn_usec
;
38 usec_t event_birth_usec
;
47 struct udev_event
*udev_event_new(sd_device
*dev
, usec_t exec_delay_usec
, sd_netlink
*rtnl
) {
48 struct udev_event
*event
;
52 event
= new(struct udev_event
, 1);
56 *event
= (struct udev_event
) {
57 .dev
= sd_device_ref(dev
),
58 .birth_usec
= now(CLOCK_MONOTONIC
),
59 .exec_delay_usec
= exec_delay_usec
,
60 .rtnl
= sd_netlink_ref(rtnl
),
66 struct udev_event
*udev_event_free(struct udev_event
*event
) {
72 sd_device_unref(event
->dev
);
73 sd_device_unref(event
->dev_db_clone
);
74 sd_netlink_unref(event
->rtnl
);
75 while ((p
= hashmap_steal_first_key(event
->run_list
)))
77 hashmap_free(event
->run_list
);
78 hashmap_free_free_free(event
->seclabel_list
);
79 free(event
->program_result
);
104 struct subst_map_entry
{
107 enum subst_type type
;
110 static const struct subst_map_entry map
[] = {
111 { .name
= "devnode", .fmt
= 'N', .type
= SUBST_DEVNODE
},
112 { .name
= "tempnode", .fmt
= 'N', .type
= SUBST_DEVNODE
},
113 { .name
= "attr", .fmt
= 's', .type
= SUBST_ATTR
},
114 { .name
= "sysfs", .fmt
= 's', .type
= SUBST_ATTR
},
115 { .name
= "env", .fmt
= 'E', .type
= SUBST_ENV
},
116 { .name
= "kernel", .fmt
= 'k', .type
= SUBST_KERNEL
},
117 { .name
= "number", .fmt
= 'n', .type
= SUBST_KERNEL_NUMBER
},
118 { .name
= "driver", .fmt
= 'd', .type
= SUBST_DRIVER
},
119 { .name
= "devpath", .fmt
= 'p', .type
= SUBST_DEVPATH
},
120 { .name
= "id", .fmt
= 'b', .type
= SUBST_ID
},
121 { .name
= "major", .fmt
= 'M', .type
= SUBST_MAJOR
},
122 { .name
= "minor", .fmt
= 'm', .type
= SUBST_MINOR
},
123 { .name
= "result", .fmt
= 'c', .type
= SUBST_RESULT
},
124 { .name
= "parent", .fmt
= 'P', .type
= SUBST_PARENT
},
125 { .name
= "name", .fmt
= 'D', .type
= SUBST_NAME
},
126 { .name
= "links", .fmt
= 'L', .type
= SUBST_LINKS
},
127 { .name
= "root", .fmt
= 'r', .type
= SUBST_ROOT
},
128 { .name
= "sys", .fmt
= 'S', .type
= SUBST_SYS
},
131 static ssize_t
subst_format_var(struct udev_event
*event
,
132 const struct subst_map_entry
*entry
, char *attr
,
133 char *dest
, size_t l
) {
134 sd_device
*parent
, *dev
= event
->dev
;
135 const char *val
= NULL
;
142 switch (entry
->type
) {
144 r
= sd_device_get_devpath(dev
, &val
);
147 l
= strpcpy(&s
, l
, val
);
150 r
= sd_device_get_sysname(dev
, &val
);
153 l
= strpcpy(&s
, l
, val
);
155 case SUBST_KERNEL_NUMBER
:
156 r
= sd_device_get_sysnum(dev
, &val
);
158 return r
== -ENOENT
? 0 : r
;
159 l
= strpcpy(&s
, l
, val
);
162 if (!event
->dev_parent
)
164 r
= sd_device_get_sysname(event
->dev_parent
, &val
);
167 l
= strpcpy(&s
, l
, val
);
170 if (!event
->dev_parent
)
172 r
= sd_device_get_driver(event
->dev_parent
, &val
);
174 return r
== -ENOENT
? 0 : r
;
175 l
= strpcpy(&s
, l
, val
);
179 char buf
[DECIMAL_STR_MAX(unsigned)];
181 r
= sd_device_get_devnum(dev
, &devnum
);
182 if (r
< 0 && r
!= -ENOENT
)
184 xsprintf(buf
, "%u", r
< 0 ? 0 : entry
->type
== SUBST_MAJOR
? major(devnum
) : minor(devnum
));
185 l
= strpcpy(&s
, l
, buf
);
192 if (!event
->program_result
)
195 /* get part of the result string */
198 i
= strtoul(attr
, &rest
, 10);
200 char result
[UTIL_PATH_SIZE
], tmp
[UTIL_PATH_SIZE
], *cpos
;
202 strscpy(result
, sizeof(result
), event
->program_result
);
205 while (cpos
[0] != '\0' && !isspace(cpos
[0]))
207 while (isspace(cpos
[0]))
213 log_error("requested part of result string not found");
216 strscpy(tmp
, sizeof(tmp
), cpos
);
217 /* %{2+}c copies the whole string from the second part on */
218 if (rest
[0] != '+') {
219 cpos
= strchr(tmp
, ' ');
223 l
= strpcpy(&s
, l
, tmp
);
225 l
= strpcpy(&s
, l
, event
->program_result
);
229 char vbuf
[UTIL_NAME_SIZE
];
236 /* try to read the value specified by "[dmi/id]product_name" */
237 if (util_resolve_subsys_kernel(attr
, vbuf
, sizeof(vbuf
), true) == 0)
240 /* try to read the attribute the device */
242 (void) sd_device_get_sysattr_value(dev
, attr
, &val
);
244 /* try to read the attribute of the parent device, other matches have selected */
245 if (!val
&& event
->dev_parent
&& event
->dev_parent
!= dev
)
246 (void) sd_device_get_sysattr_value(event
->dev_parent
, attr
, &val
);
251 /* strip trailing whitespace, and replace unwanted characters */
253 strscpy(vbuf
, sizeof(vbuf
), val
);
255 while (len
> 0 && isspace(vbuf
[--len
]))
257 count
= util_replace_chars(vbuf
, UDEV_ALLOWED_CHARS_INPUT
);
259 log_device_debug(dev
, "%i character(s) replaced", count
);
260 l
= strpcpy(&s
, l
, vbuf
);
264 r
= sd_device_get_parent(dev
, &parent
);
266 return r
== -ENODEV
? 0 : r
;
267 r
= sd_device_get_devname(parent
, &val
);
269 return r
== -ENOENT
? 0 : r
;
270 l
= strpcpy(&s
, l
, val
+ STRLEN("/dev/"));
273 r
= sd_device_get_devname(dev
, &val
);
275 return r
== -ENOENT
? 0 : r
;
276 l
= strpcpy(&s
, l
, val
);
280 l
= strpcpy(&s
, l
, event
->name
);
281 else if (sd_device_get_devname(dev
, &val
) >= 0)
282 l
= strpcpy(&s
, l
, val
+ STRLEN("/dev/"));
284 r
= sd_device_get_sysname(dev
, &val
);
287 l
= strpcpy(&s
, l
, val
);
291 FOREACH_DEVICE_DEVLINK(dev
, val
)
293 l
= strpcpy(&s
, l
, val
+ STRLEN("/dev/"));
295 l
= strpcpyl(&s
, l
, " ", val
+ STRLEN("/dev/"), NULL
);
298 l
= strpcpy(&s
, l
, "/dev");
301 l
= strpcpy(&s
, l
, "/sys");
306 r
= sd_device_get_property_value(dev
, attr
, &val
);
308 return r
== -ENOENT
? 0 : r
;
309 l
= strpcpy(&s
, l
, val
);
312 assert_not_reached("Unknown format substitution type");
318 ssize_t
udev_event_apply_format(struct udev_event
*event
,
319 const char *src
, char *dest
, size_t size
,
320 bool replace_whitespace
) {
336 const struct subst_map_entry
*entry
= NULL
;
337 char attrbuf
[UTIL_PATH_SIZE
], *attr
;
338 bool format_dollar
= false;
341 while (from
[0] != '\0') {
342 if (from
[0] == '$') {
343 /* substitute named variable */
346 if (from
[1] == '$') {
351 for (i
= 0; i
< ELEMENTSOF(map
); i
++) {
352 if (startswith(&from
[1], map
[i
].name
)) {
354 from
+= strlen(map
[i
].name
)+1;
355 format_dollar
= true;
359 } else if (from
[0] == '%') {
360 /* substitute format char */
363 if (from
[1] == '%') {
368 for (i
= 0; i
< ELEMENTSOF(map
); i
++) {
369 if (from
[1] == map
[i
].fmt
) {
378 if (l
< 2) /* need space for this char and the terminating NUL */
388 /* extract possible $format{attr} */
389 if (from
[0] == '{') {
393 for (i
= 0; from
[i
] != '}'; i
++)
394 if (from
[i
] == '\0') {
395 log_error("missing closing brace for format '%s'", src
);
399 if (i
>= sizeof(attrbuf
))
401 memcpy(attrbuf
, from
, i
);
408 subst_len
= subst_format_var(event
, entry
, attr
, s
, l
);
411 log_device_warning_errno(event
->dev
, subst_len
, "Failed to substitute variable '$%s', ignoring: %m", entry
->name
);
413 log_device_warning_errno(event
->dev
, subst_len
, "Failed to apply format '%%%c', ignoring: %m", entry
->fmt
);
418 /* SUBST_RESULT handles spaces itself */
419 if (replace_whitespace
&& entry
->type
!= SUBST_RESULT
)
420 /* util_replace_whitespace can replace in-place,
421 * and does nothing if subst_len == 0
423 subst_len
= util_replace_whitespace(s
, s
, subst_len
);
435 static int on_spawn_io(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
436 Spawn
*spawn
= userdata
;
442 assert(fd
== spawn
->fd_stdout
|| fd
== spawn
->fd_stderr
);
443 assert(!spawn
->result
|| spawn
->result_len
< spawn
->result_size
);
445 if (fd
== spawn
->fd_stdout
&& spawn
->result
) {
446 p
= spawn
->result
+ spawn
->result_len
;
447 size
= spawn
->result_size
- spawn
->result_len
;
453 l
= read(fd
, p
, size
- 1);
456 log_error_errno(errno
, "Failed to read stdout of '%s': %m", spawn
->cmd
);
462 if (fd
== spawn
->fd_stdout
&& spawn
->result
)
463 spawn
->result_len
+= l
;
465 /* Log output only if we watch stderr. */
466 if (l
> 0 && spawn
->fd_stderr
>= 0) {
467 _cleanup_strv_free_
char **v
= NULL
;
470 v
= strv_split_newlines(p
);
475 log_debug("'%s'(%s) '%s'", spawn
->cmd
,
476 fd
== spawn
->fd_stdout
? "out" : "err", *q
);
482 static int on_spawn_timeout(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
483 Spawn
*spawn
= userdata
;
484 char timeout
[FORMAT_TIMESPAN_MAX
];
488 kill_and_sigcont(spawn
->pid
, SIGKILL
);
490 log_error("Spawned process '%s' ["PID_FMT
"] timed out after %s, killing", spawn
->cmd
, spawn
->pid
,
491 format_timespan(timeout
, sizeof(timeout
), spawn
->timeout_usec
, USEC_PER_SEC
));
496 static int on_spawn_timeout_warning(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
497 Spawn
*spawn
= userdata
;
498 char timeout
[FORMAT_TIMESPAN_MAX
];
502 log_warning("Spawned process '%s' ["PID_FMT
"] is taking longer than %s to complete", spawn
->cmd
, spawn
->pid
,
503 format_timespan(timeout
, sizeof(timeout
), spawn
->timeout_warn_usec
, USEC_PER_SEC
));
508 static int on_spawn_sigchld(sd_event_source
*s
, const siginfo_t
*si
, void *userdata
) {
509 Spawn
*spawn
= userdata
;
513 switch (si
->si_code
) {
515 if (si
->si_status
== 0) {
516 log_debug("Process '%s' succeeded.", spawn
->cmd
);
517 sd_event_exit(sd_event_source_get_event(s
), 0);
522 log_full(spawn
->accept_failure
? LOG_DEBUG
: LOG_WARNING
,
523 "Process '%s' failed with exit code %i.", spawn
->cmd
, si
->si_status
);
527 log_warning("Process '%s' terminated by signal %s.", spawn
->cmd
, signal_to_string(si
->si_status
));
531 log_error("Process '%s' failed due to unknown reason.", spawn
->cmd
);
534 sd_event_exit(sd_event_source_get_event(s
), -EIO
);
539 static int spawn_wait(Spawn
*spawn
) {
540 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
545 r
= sd_event_new(&e
);
549 if (spawn
->timeout_usec
> 0) {
550 usec_t usec
, age_usec
;
552 usec
= now(CLOCK_MONOTONIC
);
553 age_usec
= usec
- spawn
->event_birth_usec
;
554 if (age_usec
< spawn
->timeout_usec
) {
555 if (spawn
->timeout_warn_usec
> 0 &&
556 spawn
->timeout_warn_usec
< spawn
->timeout_usec
&&
557 spawn
->timeout_warn_usec
> age_usec
) {
558 spawn
->timeout_warn_usec
-= age_usec
;
560 r
= sd_event_add_time(e
, NULL
, CLOCK_MONOTONIC
,
561 usec
+ spawn
->timeout_warn_usec
, USEC_PER_SEC
,
562 on_spawn_timeout_warning
, spawn
);
567 spawn
->timeout_usec
-= age_usec
;
569 r
= sd_event_add_time(e
, NULL
, CLOCK_MONOTONIC
,
570 usec
+ spawn
->timeout_usec
, USEC_PER_SEC
, on_spawn_timeout
, spawn
);
576 r
= sd_event_add_io(e
, NULL
, spawn
->fd_stdout
, EPOLLIN
, on_spawn_io
, spawn
);
580 r
= sd_event_add_io(e
, NULL
, spawn
->fd_stderr
, EPOLLIN
, on_spawn_io
, spawn
);
584 r
= sd_event_add_child(e
, NULL
, spawn
->pid
, WEXITED
, on_spawn_sigchld
, spawn
);
588 r
= sd_event_loop(e
);
592 r
= sd_event_get_exit_code(e
, &ret
);
599 int udev_event_spawn(struct udev_event
*event
,
603 char *result
, size_t ressize
) {
604 _cleanup_close_pair_
int outpipe
[2] = {-1, -1}, errpipe
[2] = {-1, -1};
605 _cleanup_strv_free_
char **argv
= NULL
;
613 assert(result
|| ressize
== 0);
615 /* pipes from child to parent */
616 if (result
|| log_get_max_level() >= LOG_INFO
)
617 if (pipe2(outpipe
, O_NONBLOCK
|O_CLOEXEC
) != 0)
618 return log_error_errno(errno
, "Failed to create pipe for command '%s': %m", cmd
);
620 if (log_get_max_level() >= LOG_INFO
)
621 if (pipe2(errpipe
, O_NONBLOCK
|O_CLOEXEC
) != 0)
622 return log_error_errno(errno
, "Failed to create pipe for command '%s': %m", cmd
);
624 argv
= strv_split_full(cmd
, NULL
, SPLIT_QUOTES
|SPLIT_RELAX
);
628 if (isempty(argv
[0]))
629 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
630 "Invalid command '%s'", cmd
);
632 /* allow programs in /usr/lib/udev/ to be called without the path */
633 if (!path_is_absolute(argv
[0])) {
636 program
= path_join(UDEVLIBEXECDIR
, argv
[0]);
640 free_and_replace(argv
[0], program
);
643 r
= device_get_properties_strv(event
->dev
, &envp
);
645 return log_device_error_errno(event
->dev
, r
, "Failed to get device properties");
647 log_debug("Starting '%s'", cmd
);
649 r
= safe_fork("(spawn)", FORK_RESET_SIGNALS
|FORK_DEATHSIG
|FORK_LOG
, &pid
);
651 return log_error_errno(r
, "Failed to fork() to execute command '%s': %m", cmd
);
653 if (rearrange_stdio(-1, outpipe
[WRITE_END
], errpipe
[WRITE_END
]) < 0)
656 (void) close_all_fds(NULL
, 0);
658 execve(argv
[0], argv
, envp
);
662 /* parent closed child's ends of pipes */
663 outpipe
[WRITE_END
] = safe_close(outpipe
[WRITE_END
]);
664 errpipe
[WRITE_END
] = safe_close(errpipe
[WRITE_END
]);
669 .accept_failure
= accept_failure
,
670 .timeout_warn_usec
= udev_warn_timeout(timeout_usec
),
671 .timeout_usec
= timeout_usec
,
672 .event_birth_usec
= event
->birth_usec
,
673 .fd_stdout
= outpipe
[READ_END
],
674 .fd_stderr
= errpipe
[READ_END
],
676 .result_size
= ressize
,
678 r
= spawn_wait(&spawn
);
680 return log_error_errno(r
, "Failed to wait spawned command '%s': %m", cmd
);
683 result
[spawn
.result_len
] = '\0';
688 static int rename_netif(struct udev_event
*event
) {
689 sd_device
*dev
= event
->dev
;
690 const char *action
, *oldname
;
695 return 0; /* No new name is requested. */
697 r
= sd_device_get_sysname(dev
, &oldname
);
699 return log_device_error_errno(dev
, r
, "Failed to get sysname: %m");
701 if (streq(event
->name
, oldname
))
702 return 0; /* The interface name is already requested name. */
704 r
= sd_device_get_property_value(dev
, "ACTION", &action
);
706 return log_device_error_errno(dev
, r
, "Failed to get property 'ACTION': %m");
708 if (!streq(action
, "add"))
709 return 0; /* Rename the interface only when it is added. */
711 r
= sd_device_get_ifindex(dev
, &ifindex
);
713 return 0; /* Device is not a network interface. */
715 return log_device_error_errno(dev
, r
, "Failed to get ifindex: %m");
717 strscpy(name
, IFNAMSIZ
, event
->name
);
718 r
= rtnl_set_link_name(&event
->rtnl
, ifindex
, name
);
720 return log_device_error_errno(dev
, r
, "Failed to rename network interface %i from '%s' to '%s': %m", ifindex
, oldname
, name
);
722 r
= device_rename(dev
, event
->name
);
724 return log_warning_errno(r
, "Network interface %i is renamed from '%s' to '%s', but could not update sd_device object: %m", ifindex
, oldname
, name
);
726 log_device_debug(dev
, "Network interface %i is renamed from '%s' to '%s'", ifindex
, oldname
, name
);
731 static int update_devnode(struct udev_event
*event
) {
732 sd_device
*dev
= event
->dev
;
737 r
= sd_device_get_devnum(dev
, NULL
);
741 return log_device_error_errno(dev
, r
, "Failed to get devnum: %m");
743 /* remove/update possible left-over symlinks from old database entry */
744 if (event
->dev_db_clone
)
745 (void) udev_node_update_old_links(dev
, event
->dev_db_clone
);
747 if (!event
->owner_set
) {
748 r
= device_get_devnode_uid(dev
, &event
->uid
);
749 if (r
< 0 && r
!= -ENOENT
)
750 return log_device_error_errno(dev
, r
, "Failed to get devnode UID: %m");
753 if (!event
->group_set
) {
754 r
= device_get_devnode_gid(dev
, &event
->gid
);
755 if (r
< 0 && r
!= -ENOENT
)
756 return log_device_error_errno(dev
, r
, "Failed to get devnode GID: %m");
759 if (!event
->mode_set
) {
760 r
= device_get_devnode_mode(dev
, &event
->mode
);
761 if (r
< 0 && r
!= -ENOENT
)
762 return log_device_error_errno(dev
, r
, "Failed to get devnode mode: %m");
765 /* default 0660 if a group is assigned */
773 r
= sd_device_get_property_value(dev
, "ACTION", &action
);
775 return log_device_error_errno(dev
, r
, "Failed to get property 'ACTION': %m");
777 apply
= streq(action
, "add") || event
->owner_set
|| event
->group_set
|| event
->mode_set
;
778 return udev_node_add(dev
, apply
, event
->mode
, event
->uid
, event
->gid
, event
->seclabel_list
);
781 static void event_execute_rules_on_remove(
782 struct udev_event
*event
,
784 Hashmap
*properties_list
,
785 struct udev_rules
*rules
) {
787 sd_device
*dev
= event
->dev
;
790 r
= device_read_db_force(dev
);
792 log_device_debug_errno(dev
, r
, "Failed to read database under /run/udev/data/: %m");
794 r
= device_tag_index(dev
, NULL
, false);
796 log_device_debug_errno(dev
, r
, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
798 r
= device_delete_db(dev
);
800 log_device_debug_errno(dev
, r
, "Failed to delete database under /run/udev/data/, ignoring: %m");
802 if (sd_device_get_devnum(dev
, NULL
) >= 0)
803 (void) udev_watch_end(dev
);
805 (void) udev_rules_apply_to_event(rules
, event
, timeout_usec
, properties_list
);
807 if (sd_device_get_devnum(dev
, NULL
) >= 0)
808 (void) udev_node_remove(dev
);
811 int udev_event_execute_rules(struct udev_event
*event
,
813 Hashmap
*properties_list
,
814 struct udev_rules
*rules
) {
815 sd_device
*dev
= event
->dev
;
816 const char *subsystem
, *action
;
822 r
= sd_device_get_subsystem(dev
, &subsystem
);
824 return log_device_error_errno(dev
, r
, "Failed to get subsystem: %m");
826 r
= sd_device_get_property_value(dev
, "ACTION", &action
);
828 return log_device_error_errno(dev
, r
, "Failed to get property 'ACTION': %m");
830 if (streq(action
, "remove")) {
831 event_execute_rules_on_remove(event
, timeout_usec
, properties_list
, rules
);
835 r
= device_clone_with_db(dev
, &event
->dev_db_clone
);
837 log_device_debug_errno(dev
, r
, "Failed to clone sd_device object, ignoring: %m");
839 if (event
->dev_db_clone
) {
840 r
= sd_device_get_devnum(dev
, NULL
);
843 log_device_debug_errno(dev
, r
, "Failed to get devnum, ignoring: %m");
845 if (streq(action
, "move")) {
846 r
= device_copy_properties(dev
, event
->dev_db_clone
);
848 log_device_debug_errno(dev
, r
, "Failed to copy properties from cloned device, ignoring: %m");
851 /* Disable watch during event processing. */
852 (void) udev_watch_end(event
->dev_db_clone
);
855 (void) udev_rules_apply_to_event(rules
, event
, timeout_usec
, properties_list
);
857 (void) rename_netif(event
);
858 (void) update_devnode(event
);
860 /* preserve old, or get new initialization timestamp */
861 r
= device_ensure_usec_initialized(dev
, event
->dev_db_clone
);
863 log_device_debug_errno(dev
, r
, "Failed to set initialization timestamp, ignoring: %m");
865 /* (re)write database file */
866 r
= device_tag_index(dev
, event
->dev_db_clone
, true);
868 log_device_debug_errno(dev
, r
, "Failed to update tags under /run/udev/tag/, ignoring: %m");
870 r
= device_update_db(dev
);
872 log_device_debug_errno(dev
, r
, "Failed to update database under /run/udev/data/, ignoring: %m");
874 device_set_is_initialized(dev
);
876 event
->dev_db_clone
= sd_device_unref(event
->dev_db_clone
);
881 void udev_event_execute_run(struct udev_event
*event
, usec_t timeout_usec
) {
886 HASHMAP_FOREACH_KEY(val
, cmd
, event
->run_list
, i
) {
887 enum udev_builtin_cmd builtin_cmd
= PTR_TO_INT(val
);
888 char command
[UTIL_PATH_SIZE
];
890 udev_event_apply_format(event
, cmd
, command
, sizeof(command
), false);
892 if (builtin_cmd
>= 0 && builtin_cmd
< _UDEV_BUILTIN_MAX
)
893 udev_builtin_run(event
->dev
, builtin_cmd
, command
, false);
895 if (event
->exec_delay_usec
> 0) {
896 log_debug("delay execution of '%s'", command
);
897 (void) usleep(event
->exec_delay_usec
);
900 udev_event_spawn(event
, timeout_usec
, false, command
, NULL
, 0);