]>
git.ipfire.org Git - thirdparty/systemd.git/blob - udevmonitor.c
2 * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <sys/socket.h>
31 #include <sys/select.h>
32 #include <linux/types.h>
33 #include <linux/netlink.h>
38 static int uevent_netlink_sock
= -1;
39 static int udev_monitor_sock
= -1;
40 static volatile int udev_exit
;
42 static int init_udev_monitor_socket(void)
44 struct sockaddr_un saddr
;
46 const int feature_on
= 1;
49 memset(&saddr
, 0x00, sizeof(saddr
));
50 saddr
.sun_family
= AF_LOCAL
;
51 /* use abstract namespace for socket path */
52 strcpy(&saddr
.sun_path
[1], "/org/kernel/udev/monitor");
53 addrlen
= offsetof(struct sockaddr_un
, sun_path
) + strlen(saddr
.sun_path
+1) + 1;
55 udev_monitor_sock
= socket(AF_LOCAL
, SOCK_DGRAM
, 0);
56 if (udev_monitor_sock
== -1) {
57 fprintf(stderr
, "error getting socket: %s\n", strerror(errno
));
61 /* the bind takes care of ensuring only one copy running */
62 retval
= bind(udev_monitor_sock
, (struct sockaddr
*) &saddr
, addrlen
);
64 fprintf(stderr
, "bind failed: %s\n", strerror(errno
));
65 close(udev_monitor_sock
);
66 udev_monitor_sock
= -1;
70 /* enable receiving of the sender credentials */
71 setsockopt(udev_monitor_sock
, SOL_SOCKET
, SO_PASSCRED
, &feature_on
, sizeof(feature_on
));
76 static int init_uevent_netlink_sock(void)
78 struct sockaddr_nl snl
;
81 memset(&snl
, 0x00, sizeof(struct sockaddr_nl
));
82 snl
.nl_family
= AF_NETLINK
;
83 snl
.nl_pid
= getpid();
86 uevent_netlink_sock
= socket(PF_NETLINK
, SOCK_DGRAM
, NETLINK_KOBJECT_UEVENT
);
87 if (uevent_netlink_sock
== -1) {
88 fprintf(stderr
, "error getting socket: %s\n", strerror(errno
));
92 retval
= bind(uevent_netlink_sock
, (struct sockaddr
*) &snl
,
93 sizeof(struct sockaddr_nl
));
95 fprintf(stderr
, "bind failed: %s\n", strerror(errno
));
96 close(uevent_netlink_sock
);
97 uevent_netlink_sock
= -1;
104 static void asmlinkage
sig_handler(int signum
)
106 if (signum
== SIGINT
|| signum
== SIGTERM
)
110 static const char *search_key(const char *searchkey
, const char *buf
, size_t buflen
)
113 size_t searchkeylen
= strlen(searchkey
);
115 while (bufpos
< buflen
) {
120 keylen
= strlen(key
);
123 if ((strncmp(searchkey
, key
, searchkeylen
) == 0) && key
[searchkeylen
] == '=')
124 return &key
[searchkeylen
+ 1];
125 bufpos
+= keylen
+ 1;
130 int main(int argc
, char *argv
[])
132 struct sigaction act
;
140 static const struct option options
[] = {
141 { "environment", 0, NULL
, 'e' },
142 { "kernel", 0, NULL
, 'k' },
143 { "udev", 0, NULL
, 'u' },
144 { "help", 0, NULL
, 'h' },
149 option
= getopt_long(argc
, argv
, "ekuh", options
, NULL
);
164 printf("Usage: udevmonitor [--environment] [--kernel] [--udev] [--help]\n"
165 " --env print the whole event environment\n"
166 " --kernel print kernel uevents\n"
167 " --udev print udev events\n"
168 " --help print this help text\n\n");
174 if (!kernel
&& !udev
) {
179 if (getuid() != 0 && kernel
) {
180 fprintf(stderr
, "root privileges needed to subscribe to kernel events\n");
184 /* set signal handlers */
185 memset(&act
, 0x00, sizeof(struct sigaction
));
186 act
.sa_handler
= (void (*)(int)) sig_handler
;
187 sigemptyset(&act
.sa_mask
);
188 act
.sa_flags
= SA_RESTART
;
189 sigaction(SIGINT
, &act
, NULL
);
190 sigaction(SIGTERM
, &act
, NULL
);
192 printf("udevmonitor will print the received events for:\n");
194 retval
= init_udev_monitor_socket();
197 printf("UDEV the event which udev sends out after rule processing\n");
200 retval
= init_uevent_netlink_sock();
203 printf("UEVENT the kernel uevent\n");
208 char buf
[UEVENT_BUFFER_SIZE
*2];
216 const char *source
= NULL
;
217 const char *devpath
, *action
, *subsys
;
221 if (uevent_netlink_sock
>= 0)
222 FD_SET(uevent_netlink_sock
, &readfds
);
223 if (udev_monitor_sock
>= 0)
224 FD_SET(udev_monitor_sock
, &readfds
);
226 fdcount
= select(UDEV_MAX(uevent_netlink_sock
, udev_monitor_sock
)+1, &readfds
, NULL
, NULL
, NULL
);
229 fprintf(stderr
, "error receiving uevent message: %s\n", strerror(errno
));
233 if (gettimeofday(&tv
, &tz
) == 0) {
234 snprintf(timestr
, sizeof(timestr
), "%llu.%06u",
235 (unsigned long long) tv
.tv_sec
, (unsigned int) tv
.tv_usec
);
239 if ((uevent_netlink_sock
>= 0) && FD_ISSET(uevent_netlink_sock
, &readfds
)) {
240 buflen
= recv(uevent_netlink_sock
, &buf
, sizeof(buf
), 0);
242 fprintf(stderr
, "error receiving uevent message: %s\n", strerror(errno
));
248 if ((udev_monitor_sock
>= 0) && FD_ISSET(udev_monitor_sock
, &readfds
)) {
249 buflen
= recv(udev_monitor_sock
, &buf
, sizeof(buf
), 0);
251 fprintf(stderr
, "error receiving udev message: %s\n", strerror(errno
));
260 keys
= strlen(buf
) + 1; /* start of payload */
261 devpath
= search_key("DEVPATH", &buf
[keys
], buflen
);
262 action
= search_key("ACTION", &buf
[keys
], buflen
);
263 subsys
= search_key("SUBSYSTEM", &buf
[keys
], buflen
);
264 printf("%s[%s] %-8s %s (%s)\n", source
, timestr
, action
, devpath
, subsys
);
266 /* print environment */
269 while (bufpos
< buflen
) {
274 keylen
= strlen(key
);
278 bufpos
+= keylen
+ 1;
285 if (uevent_netlink_sock
>= 0)
286 close(uevent_netlink_sock
);
287 if (udev_monitor_sock
>= 0)
288 close(udev_monitor_sock
);