1 /* SPDX-License-Identifier: GPL-2.0+ */
14 #include "format-util.h"
16 #include "udevadm-util.h"
18 static bool udev_exit
;
20 static void sig_handler(int signum
) {
21 if (IN_SET(signum
, SIGINT
, SIGTERM
))
25 static void print_device(struct udev_device
*device
, const char *source
, int prop
) {
28 assert_se(clock_gettime(CLOCK_MONOTONIC
, &ts
) == 0);
29 printf("%-6s[%"PRI_TIME
".%06"PRI_NSEC
"] %-8s %s (%s)\n",
31 ts
.tv_sec
, (nsec_t
)ts
.tv_nsec
/1000,
32 udev_device_get_action(device
),
33 udev_device_get_devpath(device
),
34 udev_device_get_subsystem(device
));
36 struct udev_list_entry
*list_entry
;
38 udev_list_entry_foreach(list_entry
, udev_device_get_properties_list_entry(device
))
40 udev_list_entry_get_name(list_entry
),
41 udev_list_entry_get_value(list_entry
));
46 static void help(void) {
47 printf("%s monitor [OPTIONS]\n\n"
48 "Listen to kernel and udev events.\n\n"
49 " -h --help Show this help\n"
50 " -V --version Show package version\n"
51 " -p --property Print the event properties\n"
52 " -k --kernel Print kernel uevents\n"
53 " -u --udev Print udev events\n"
54 " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
55 " -t --tag-match=TAG Filter events by tag\n"
56 , program_invocation_short_name
);
59 static int adm_monitor(int argc
, char *argv
[]) {
60 struct sigaction act
= {};
63 bool print_kernel
= false;
64 bool print_udev
= false;
65 _cleanup_(udev_list_cleanup
) struct udev_list subsystem_match_list
;
66 _cleanup_(udev_list_cleanup
) struct udev_list tag_match_list
;
67 _cleanup_(udev_monitor_unrefp
) struct udev_monitor
*udev_monitor
= NULL
;
68 _cleanup_(udev_monitor_unrefp
) struct udev_monitor
*kernel_monitor
= NULL
;
69 _cleanup_close_
int fd_ep
= -1;
70 int fd_kernel
= -1, fd_udev
= -1;
71 struct epoll_event ep_kernel
, ep_udev
;
74 static const struct option options
[] = {
75 { "property", no_argument
, NULL
, 'p' },
76 { "environment", no_argument
, NULL
, 'e' }, /* alias for -p */
77 { "kernel", no_argument
, NULL
, 'k' },
78 { "udev", no_argument
, NULL
, 'u' },
79 { "subsystem-match", required_argument
, NULL
, 's' },
80 { "tag-match", required_argument
, NULL
, 't' },
81 { "version", no_argument
, NULL
, 'V' },
82 { "help", no_argument
, NULL
, 'h' },
86 udev_list_init(NULL
, &subsystem_match_list
, true);
87 udev_list_init(NULL
, &tag_match_list
, true);
89 while ((c
= getopt_long(argc
, argv
, "pekus:t:Vh", options
, NULL
)) >= 0)
103 char subsys
[UTIL_NAME_SIZE
];
106 strscpy(subsys
, sizeof(subsys
), optarg
);
107 devtype
= strchr(subsys
, '/');
108 if (devtype
!= NULL
) {
112 udev_list_entry_add(&subsystem_match_list
, subsys
, devtype
);
116 udev_list_entry_add(&tag_match_list
, optarg
, NULL
);
128 if (!print_kernel
&& !print_udev
) {
133 /* set signal handlers */
134 act
.sa_handler
= sig_handler
;
135 act
.sa_flags
= SA_RESTART
;
136 assert_se(sigaction(SIGINT
, &act
, NULL
) == 0);
137 assert_se(sigaction(SIGTERM
, &act
, NULL
) == 0);
138 assert_se(sigemptyset(&mask
) == 0);
139 assert_se(sigaddset(&mask
, SIGINT
) == 0);
140 assert_se(sigaddset(&mask
, SIGTERM
) == 0);
141 assert_se(sigprocmask(SIG_UNBLOCK
, &mask
, NULL
) == 0);
143 /* Callers are expecting to see events as they happen: Line buffering */
146 fd_ep
= epoll_create1(EPOLL_CLOEXEC
);
148 log_error_errno(errno
, "error creating epoll fd: %m");
152 printf("monitor will print the received events for:\n");
154 struct udev_list_entry
*entry
;
156 udev_monitor
= udev_monitor_new_from_netlink(NULL
, "udev");
157 if (udev_monitor
== NULL
) {
158 fprintf(stderr
, "error: unable to create netlink socket\n");
161 udev_monitor_set_receive_buffer_size(udev_monitor
, 128*1024*1024);
162 fd_udev
= udev_monitor_get_fd(udev_monitor
);
164 udev_list_entry_foreach(entry
, udev_list_get_entry(&subsystem_match_list
)) {
165 const char *subsys
= udev_list_entry_get_name(entry
);
166 const char *devtype
= udev_list_entry_get_value(entry
);
168 if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor
, subsys
, devtype
) < 0)
169 fprintf(stderr
, "error: unable to apply subsystem filter '%s'\n", subsys
);
172 udev_list_entry_foreach(entry
, udev_list_get_entry(&tag_match_list
)) {
173 const char *tag
= udev_list_entry_get_name(entry
);
175 if (udev_monitor_filter_add_match_tag(udev_monitor
, tag
) < 0)
176 fprintf(stderr
, "error: unable to apply tag filter '%s'\n", tag
);
179 if (udev_monitor_enable_receiving(udev_monitor
) < 0) {
180 fprintf(stderr
, "error: unable to subscribe to udev events\n");
184 memzero(&ep_udev
, sizeof(struct epoll_event
));
185 ep_udev
.events
= EPOLLIN
;
186 ep_udev
.data
.fd
= fd_udev
;
187 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, fd_udev
, &ep_udev
) < 0) {
188 log_error_errno(errno
, "fail to add fd to epoll: %m");
192 printf("UDEV - the event which udev sends out after rule processing\n");
196 struct udev_list_entry
*entry
;
198 kernel_monitor
= udev_monitor_new_from_netlink(NULL
, "kernel");
199 if (kernel_monitor
== NULL
) {
200 fprintf(stderr
, "error: unable to create netlink socket\n");
203 udev_monitor_set_receive_buffer_size(kernel_monitor
, 128*1024*1024);
204 fd_kernel
= udev_monitor_get_fd(kernel_monitor
);
206 udev_list_entry_foreach(entry
, udev_list_get_entry(&subsystem_match_list
)) {
207 const char *subsys
= udev_list_entry_get_name(entry
);
209 if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor
, subsys
, NULL
) < 0)
210 fprintf(stderr
, "error: unable to apply subsystem filter '%s'\n", subsys
);
213 if (udev_monitor_enable_receiving(kernel_monitor
) < 0) {
214 fprintf(stderr
, "error: unable to subscribe to kernel events\n");
218 memzero(&ep_kernel
, sizeof(struct epoll_event
));
219 ep_kernel
.events
= EPOLLIN
;
220 ep_kernel
.data
.fd
= fd_kernel
;
221 if (epoll_ctl(fd_ep
, EPOLL_CTL_ADD
, fd_kernel
, &ep_kernel
) < 0) {
222 log_error_errno(errno
, "fail to add fd to epoll: %m");
226 printf("KERNEL - the kernel uevent\n");
232 struct epoll_event ev
[4];
235 fdcount
= epoll_wait(fd_ep
, ev
, ELEMENTSOF(ev
), -1);
238 fprintf(stderr
, "error receiving uevent message: %m\n");
242 for (i
= 0; i
< fdcount
; i
++) {
243 if (ev
[i
].data
.fd
== fd_kernel
&& ev
[i
].events
& EPOLLIN
) {
244 struct udev_device
*device
;
246 device
= udev_monitor_receive_device(kernel_monitor
);
249 print_device(device
, "KERNEL", prop
);
250 udev_device_unref(device
);
251 } else if (ev
[i
].data
.fd
== fd_udev
&& ev
[i
].events
& EPOLLIN
) {
252 struct udev_device
*device
;
254 device
= udev_monitor_receive_device(udev_monitor
);
257 print_device(device
, "UDEV", prop
);
258 udev_device_unref(device
);
266 const struct udevadm_cmd udevadm_monitor
= {
269 .help
= "Listen to kernel and udev events",