1 /* SPDX-License-Identifier: GPL-2.0+ */
12 #include <sys/epoll.h>
17 #include "format-util.h"
18 #include "udev-util.h"
20 #include "udevadm-util.h"
22 static bool udev_exit
;
24 static void sig_handler(int signum
) {
25 if (IN_SET(signum
, SIGINT
, SIGTERM
))
29 static void print_device(struct udev_device
*device
, const char *source
, int prop
) {
32 assert_se(clock_gettime(CLOCK_MONOTONIC
, &ts
) == 0);
33 printf("%-6s[%"PRI_TIME
".%06"PRI_NSEC
"] %-8s %s (%s)\n",
35 ts
.tv_sec
, (nsec_t
)ts
.tv_nsec
/1000,
36 udev_device_get_action(device
),
37 udev_device_get_devpath(device
),
38 udev_device_get_subsystem(device
));
40 struct udev_list_entry
*list_entry
;
42 udev_list_entry_foreach(list_entry
, udev_device_get_properties_list_entry(device
))
44 udev_list_entry_get_name(list_entry
),
45 udev_list_entry_get_value(list_entry
));
50 static void help(void) {
51 printf("%s monitor [OPTIONS]\n\n"
52 "Listen to kernel and udev events.\n\n"
53 " -h --help Show this help\n"
54 " -V --version Show package version\n"
55 " -p --property Print the event properties\n"
56 " -k --kernel Print kernel uevents\n"
57 " -u --udev Print udev events\n"
58 " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
59 " -t --tag-match=TAG Filter events by tag\n"
60 , program_invocation_short_name
);
63 static int adm_monitor(struct udev
*udev
, int argc
, char *argv
[]) {
64 struct sigaction act
= {};
67 bool print_kernel
= false;
68 bool print_udev
= false;
69 _cleanup_(udev_list_cleanup
) struct udev_list subsystem_match_list
;
70 _cleanup_(udev_list_cleanup
) struct udev_list tag_match_list
;
71 _cleanup_(udev_monitor_unrefp
) struct udev_monitor
*udev_monitor
= NULL
;
72 _cleanup_(udev_monitor_unrefp
) struct udev_monitor
*kernel_monitor
= NULL
;
73 _cleanup_close_
int fd_ep
= -1;
74 int fd_kernel
= -1, fd_udev
= -1;
75 struct epoll_event ep_kernel
, ep_udev
;
78 static const struct option options
[] = {
79 { "property", no_argument
, NULL
, 'p' },
80 { "environment", no_argument
, NULL
, 'e' }, /* alias for -p */
81 { "kernel", no_argument
, NULL
, 'k' },
82 { "udev", no_argument
, NULL
, 'u' },
83 { "subsystem-match", required_argument
, NULL
, 's' },
84 { "tag-match", required_argument
, NULL
, 't' },
85 { "version", no_argument
, NULL
, 'V' },
86 { "help", no_argument
, NULL
, 'h' },
90 udev_list_init(udev
, &subsystem_match_list
, true);
91 udev_list_init(udev
, &tag_match_list
, true);
93 while ((c
= getopt_long(argc
, argv
, "pekus:t:Vh", options
, NULL
)) >= 0)
107 char subsys
[UTIL_NAME_SIZE
];
110 strscpy(subsys
, sizeof(subsys
), optarg
);
111 devtype
= strchr(subsys
, '/');
112 if (devtype
!= NULL
) {
116 udev_list_entry_add(&subsystem_match_list
, subsys
, devtype
);
120 udev_list_entry_add(&tag_match_list
, optarg
, NULL
);
132 if (!print_kernel
&& !print_udev
) {
137 /* set signal handlers */
138 act
.sa_handler
= sig_handler
;
139 act
.sa_flags
= SA_RESTART
;
140 assert_se(sigaction(SIGINT
, &act
, NULL
) == 0);
141 assert_se(sigaction(SIGTERM
, &act
, NULL
) == 0);
142 assert_se(sigemptyset(&mask
) == 0);
143 assert_se(sigaddset(&mask
, SIGINT
) == 0);
144 assert_se(sigaddset(&mask
, SIGTERM
) == 0);
145 assert_se(sigprocmask(SIG_UNBLOCK
, &mask
, NULL
) == 0);
147 /* Callers are expecting to see events as they happen: Line buffering */
150 fd_ep
= epoll_create1(EPOLL_CLOEXEC
);
152 log_error_errno(errno
, "error creating epoll fd: %m");
156 printf("monitor will print the received events for:\n");
158 struct udev_list_entry
*entry
;
160 udev_monitor
= udev_monitor_new_from_netlink(udev
, "udev");
161 if (udev_monitor
== NULL
) {
162 fprintf(stderr
, "error: unable to create netlink socket\n");
165 udev_monitor_set_receive_buffer_size(udev_monitor
, 128*1024*1024);
166 fd_udev
= udev_monitor_get_fd(udev_monitor
);
168 udev_list_entry_foreach(entry
, udev_list_get_entry(&subsystem_match_list
)) {
169 const char *subsys
= udev_list_entry_get_name(entry
);
170 const char *devtype
= udev_list_entry_get_value(entry
);
172 if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor
, subsys
, devtype
) < 0)
173 fprintf(stderr
, "error: unable to apply subsystem filter '%s'\n", subsys
);
176 udev_list_entry_foreach(entry
, udev_list_get_entry(&tag_match_list
)) {
177 const char *tag
= udev_list_entry_get_name(entry
);
179 if (udev_monitor_filter_add_match_tag(udev_monitor
, tag
) < 0)
180 fprintf(stderr
, "error: unable to apply tag filter '%s'\n", tag
);
183 if (udev_monitor_enable_receiving(udev_monitor
) < 0) {
184 fprintf(stderr
, "error: unable to subscribe to udev events\n");
188 memzero(&ep_udev
, sizeof(struct epoll_event
));
189 ep_udev
.events
= EPOLLIN
;
190 ep_udev
.data
.fd
= fd_udev
;
191 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, fd_udev
, &ep_udev
) < 0) {
192 log_error_errno(errno
, "fail to add fd to epoll: %m");
196 printf("UDEV - the event which udev sends out after rule processing\n");
200 struct udev_list_entry
*entry
;
202 kernel_monitor
= udev_monitor_new_from_netlink(udev
, "kernel");
203 if (kernel_monitor
== NULL
) {
204 fprintf(stderr
, "error: unable to create netlink socket\n");
207 udev_monitor_set_receive_buffer_size(kernel_monitor
, 128*1024*1024);
208 fd_kernel
= udev_monitor_get_fd(kernel_monitor
);
210 udev_list_entry_foreach(entry
, udev_list_get_entry(&subsystem_match_list
)) {
211 const char *subsys
= udev_list_entry_get_name(entry
);
213 if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor
, subsys
, NULL
) < 0)
214 fprintf(stderr
, "error: unable to apply subsystem filter '%s'\n", subsys
);
217 if (udev_monitor_enable_receiving(kernel_monitor
) < 0) {
218 fprintf(stderr
, "error: unable to subscribe to kernel events\n");
222 memzero(&ep_kernel
, sizeof(struct epoll_event
));
223 ep_kernel
.events
= EPOLLIN
;
224 ep_kernel
.data
.fd
= fd_kernel
;
225 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, fd_kernel
, &ep_kernel
) < 0) {
226 log_error_errno(errno
, "fail to add fd to epoll: %m");
230 printf("KERNEL - the kernel uevent\n");
236 struct epoll_event ev
[4];
239 fdcount
= epoll_wait(fd_ep
, ev
, ELEMENTSOF(ev
), -1);
242 fprintf(stderr
, "error receiving uevent message: %m\n");
246 for (i
= 0; i
< fdcount
; i
++) {
247 if (ev
[i
].data
.fd
== fd_kernel
&& ev
[i
].events
& EPOLLIN
) {
248 struct udev_device
*device
;
250 device
= udev_monitor_receive_device(kernel_monitor
);
253 print_device(device
, "KERNEL", prop
);
254 udev_device_unref(device
);
255 } else if (ev
[i
].data
.fd
== fd_udev
&& ev
[i
].events
& EPOLLIN
) {
256 struct udev_device
*device
;
258 device
= udev_monitor_receive_device(udev_monitor
);
261 print_device(device
, "UDEV", prop
);
262 udev_device_unref(device
);
270 const struct udevadm_cmd udevadm_monitor
= {
273 .help
= "Listen to kernel and udev events",