X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev%2Fudevadm-monitor.c;h=73516069ba6f42efd12c7b0a15772b99dc7450e6;hb=48a9b173e88738ff4eefb3519f1d27711b417c8d;hp=a798a81626734c5ee4db41518c6ad018819168d6;hpb=55e9959b155cefc5146f7a3d1ea73e74da91f303;p=elogind.git diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c index a798a8162..73516069b 100644 --- a/udev/udevadm-monitor.c +++ b/udev/udevadm-monitor.c @@ -35,52 +35,68 @@ static int udev_exit; -static void asmlinkage sig_handler(int signum) +static void sig_handler(int signum) { if (signum == SIGINT || signum == SIGTERM) udev_exit = 1; } -static int print_properties_cb(struct udev_device *udev_device, const char *key, const char *value, void *data) +static void print_device(struct udev_device *device, const char *source, int prop) { - printf("%s=%s\n", key, value); - return 0; -} - -static void print_properties(struct udev_device *device) -{ - udev_device_get_properties(device, print_properties_cb, NULL); - printf("\n"); + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + printf("%-6s[%llu.%06u] %-8s %s (%s)\n", + source, + (unsigned long long) tv.tv_sec, (unsigned int) tv.tv_usec, + udev_device_get_action(device), + udev_device_get_devpath(device), + udev_device_get_subsystem(device)); + if (prop) { + struct udev_list_entry *list_entry; + + udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) + printf("%s=%s\n", + udev_list_entry_get_name(list_entry), + udev_list_entry_get_value(list_entry)); + printf("\n"); + } } int udevadm_monitor(struct udev *udev, int argc, char *argv[]) { struct sigaction act; int option; - int env = 0; + int prop = 0; int print_kernel = 0; int print_udev = 0; + struct udev_list_node subsystem_match_list; struct udev_monitor *udev_monitor = NULL; struct udev_monitor *kernel_monitor = NULL; fd_set readfds; int rc = 0; static const struct option options[] = { - { "environment", 0, NULL, 'e' }, - { "kernel", 0, NULL, 'k' }, - { "udev", 0, NULL, 'u' }, - { "help", 0, NULL, 'h' }, + { "property", no_argument, NULL, 'p' }, + { "environment", no_argument, NULL, 'e' }, + { "kernel", no_argument, NULL, 'k' }, + { "udev", no_argument, NULL, 'u' }, + { "subsystem-match", required_argument, NULL, 's' }, + { "help", no_argument, NULL, 'h' }, {} }; + udev_list_init(&subsystem_match_list); while (1) { - option = getopt_long(argc, argv, "ekuh", options, NULL); + option = getopt_long(argc, argv, "epkus:h", options, NULL); if (option == -1) break; switch (option) { + case 'p': case 'e': - env = 1; + prop = 1; break; case 'k': print_kernel = 1; @@ -88,12 +104,27 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) case 'u': print_udev = 1; break; + case 's': + { + char subsys[UTIL_NAME_SIZE]; + char *devtype; + + util_strscpy(subsys, sizeof(subsys), optarg); + devtype = strchr(subsys, ':'); + if (devtype != NULL) { + devtype[0] = '\0'; + devtype++; + } + udev_list_entry_add(udev, &subsystem_match_list, subsys, devtype, 0, 0); + break; + } case 'h': - printf("Usage: udevadm monitor [--environment] [--kernel] [--udev] [--help]\n" - " --env print the whole event environment\n" - " --kernel print kernel uevents\n" - " --udev print udev events\n" - " --help print this help text\n\n"); + printf("Usage: udevadm monitor [--property] [--kernel] [--udev] [--help]\n" + " --property print the event properties\n" + " --kernel print kernel uevents\n" + " --udev print udev events\n" + " --subsystem-match= filter events\n" + " --help\n\n"); default: goto out; } @@ -104,14 +135,9 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) print_udev =1; } - if (getuid() != 0 && print_kernel) { - fprintf(stderr, "root privileges needed to subscribe to kernel events\n"); - goto out; - } - /* set signal handlers */ memset(&act, 0x00, sizeof(struct sigaction)); - act.sa_handler = (void (*)(int)) sig_handler; + act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGINT, &act, NULL); @@ -119,36 +145,58 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) printf("monitor will print the received events for:\n"); if (print_udev) { - udev_monitor = udev_monitor_new_from_socket(udev, "@/org/kernel/udev/monitor"); + struct udev_list_entry *entry; + + udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (udev_monitor == NULL) { + fprintf(stderr, "error: unable to create netlink socket\n"); rc = 1; goto out; } + + udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { + const char *subsys = udev_list_entry_get_name(entry); + const char *devtype = udev_list_entry_get_value(entry); + + if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, subsys, devtype) < 0) + fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); + } + if (udev_monitor_enable_receiving(udev_monitor) < 0) { + fprintf(stderr, "error: unable to subscribe to udev events\n"); rc = 2; goto out; } - printf("UDEV the event which udev sends out after rule processing\n"); + printf("UDEV - the event which udev sends out after rule processing\n"); } if (print_kernel) { - kernel_monitor = udev_monitor_new_from_netlink(udev); + struct udev_list_entry *entry; + + kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (kernel_monitor == NULL) { + fprintf(stderr, "error: unable to create netlink socket\n"); rc = 3; goto out; } + + udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { + const char *subsys = udev_list_entry_get_name(entry); + + if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, subsys, NULL) < 0) + fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); + } + if (udev_monitor_enable_receiving(kernel_monitor) < 0) { + fprintf(stderr, "error: unable to subscribe to kernel events\n"); rc = 4; goto out; } - printf("UEVENT the kernel uevent\n"); + printf("KERNEL - the kernel uevent\n"); } printf("\n"); while (!udev_exit) { int fdcount; - struct timeval tv; - struct timezone tz; - char timestr[64]; FD_ZERO(&readfds); if (kernel_monitor != NULL) @@ -160,39 +208,27 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) &readfds, NULL, NULL, NULL); if (fdcount < 0) { if (errno != EINTR) - fprintf(stderr, "error receiving uevent message: %s\n", strerror(errno)); + fprintf(stderr, "error receiving uevent message: %m\n"); continue; } - if (gettimeofday(&tv, &tz) == 0) { - snprintf(timestr, sizeof(timestr), "%llu.%06u", - (unsigned long long) tv.tv_sec, (unsigned int) tv.tv_usec); - } else - timestr[0] = '\0'; - if ((kernel_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(kernel_monitor), &readfds)) { - struct udev_device *device = udev_monitor_receive_device(kernel_monitor); + struct udev_device *device; + + device = udev_monitor_receive_device(kernel_monitor); if (device == NULL) continue; - printf("UEVENT[%s] %-8s %s (%s)\n", timestr, - udev_device_get_action(device), - udev_device_get_devpath(device), - udev_device_get_subsystem(device)); - if (env) - print_properties(device); + print_device(device, "KERNEL", prop); udev_device_unref(device); } if ((udev_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(udev_monitor), &readfds)) { - struct udev_device *device = udev_monitor_receive_device(udev_monitor); + struct udev_device *device; + + device = udev_monitor_receive_device(udev_monitor); if (device == NULL) continue; - printf("UDEV [%s] %-8s %s (%s)\n", timestr, - udev_device_get_action(device), - udev_device_get_devpath(device), - udev_device_get_subsystem(device)); - if (env) - print_properties(device); + print_device(device, "UDEV", prop); udev_device_unref(device); } } @@ -200,5 +236,6 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) out: udev_monitor_unref(udev_monitor); udev_monitor_unref(kernel_monitor); + udev_list_cleanup_entries(udev, &subsystem_match_list); return rc; }