nlmon

NetLink MONitor; a lightweight udevadm monitor replacement.
git clone git://r-36.net/nlmon
Log | Files | Refs | LICENSE

commit 24284ee0dcbbe18246633b903585afe40728c770
parent de28e91664d7cb3aab511b0bb853859b2ed66a30
Author: Christoph Lohmann <20h@r-36.net>
Date:   Fri,  6 Apr 2012 23:37:32 +0200

Removing libudev dependency.

Diffstat:
README.md | 11-----------
config.mk | 2+-
nlmon.c | 186++++++++++++++++++++++++++++++++-----------------------------------------------
3 files changed, 76 insertions(+), 123 deletions(-)

diff --git a/README.md b/README.md @@ -1,11 +0,0 @@ -# NetLink MONitor - -This simple utility is a replacement for udevadm monitor, which -is full of bugs. It will listen on either the kernel (-k) or the -udev (-u) events and print out the standard device parameters, -the properties (-p), the tags (-t) and the devlinks (-l). You -can filter (-f $subsystem) for the subsystem you only want to -see events for. - -Have fun! - diff --git a/config.mk b/config.mk @@ -10,7 +10,7 @@ MANPREFIX = ${PREFIX}/share/man # includes and libs INCS = -I. -I/usr/include -LIBS = -L/usr/lib -lc -ludev +LIBS = -L/usr/lib -lc # flags CPPFLAGS = -DVERSION=\"${VERSION}\" diff --git a/nlmon.c b/nlmon.c @@ -6,162 +6,126 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> -#include <libudev.h> +#include <stdarg.h> #include <poll.h> #include <ctype.h> #include <string.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <linux/types.h> +#include <linux/netlink.h> #include "arg.h" char *argv0; void -printdevice(struct udev_device *dev) +edie(char *fmt, ...) { - char *s; + va_list fmtargs; -#define PRINTELEM(NAME) \ - s = (char *)udev_device_get_##NAME(dev); \ - if (s != NULL) \ - printf(#NAME "=%s\n", udev_device_get_##NAME(dev)); + va_start(fmtargs, fmt); + vfprintf(stderr, fmt, fmtargs); + va_end(fmtargs); + fprintf(stderr, ": "); - PRINTELEM(devpath) - PRINTELEM(subsystem) - PRINTELEM(devtype) - PRINTELEM(syspath) - PRINTELEM(sysnum) - PRINTELEM(devnode) - PRINTELEM(driver) + perror(NULL); - printf("devnum=%d\n", (int)udev_device_get_devnum(dev)); - - PRINTELEM(action) - fflush(stdout); + exit(1); } void -printproperties(struct udev_device *dev) +die(char *fmt, ...) { - struct udev_list_entry *props, *prop; - - props = udev_device_get_properties_list_entry(dev); - udev_list_entry_foreach(prop, props) { - printf("%s=%s\n", udev_list_entry_get_name(prop), \ - udev_list_entry_get_value(prop)); - } - fflush(stdout); -} + va_list fmtargs; -void -printtags(struct udev_device *dev) -{ - struct udev_list_entry *tags, *tag; + va_start(fmtargs, fmt); + vfprintf(stderr, fmt, fmtargs); + va_end(fmtargs); - tags = udev_device_get_tags_list_entry(dev); - udev_list_entry_foreach(tag, tags) { - printf("%s=%s\n", udev_list_entry_get_name(tag), \ - udev_list_entry_get_value(tag)); - } - fflush(stdout); -} - -void -printdevlinks(struct udev_device *dev) -{ - struct udev_list_entry *devlinks, *devlink; - - devlinks = udev_device_get_devlinks_list_entry(dev); - udev_list_entry_foreach(devlink, devlinks) { - printf("%s=%s\n", udev_list_entry_get_name(devlink), \ - udev_list_entry_get_value(devlink)); - } - fflush(stdout); + exit(1); } void usage(void) { - fprintf(stderr, "usage: %s [-ptl] [-ku] [-f filter]\n", argv0); - fflush(stderr); - exit(EXIT_FAILURE); + die("usage: %s [-h] [-ku] [-f subsystem]\n", argv0); } int main(int argc, char *argv[]) { - char *filter, *rtlink; - struct udev *udev; - struct udev_monitor *mon; - struct udev_device *dev; - struct pollfd fds[1]; - int ret, doprops, dotags, dolinks; - - filter = NULL; - doprops = 0; - dotags = 0; - dolinks = 0; - rtlink = "kernel"; + struct sockaddr_nl nls; + struct pollfd fds; + char buf[4097], obuf[4098], *subsystem; + int i, len, olen, slen, showudev, showkernel; + + showkernel = 1; + showudev = 1; + subsystem = NULL; ARGBEGIN { case 'f': - filter = EARGF(usage()); - break; - case 'p': - doprops = 1; - break; - case 'l': - dolinks = 1; - break; - case 't': - dotags = 1; + subsystem = EARGF(usage()); break; case 'k': - rtlink = "kernel"; + showudev = 0; break; case 'u': - rtlink = "udev"; + showkernel = 0; break; default: usage(); } ARGEND; - udev = udev_new(); - if (!udev) { - perror("udev_new"); - exit(EXIT_FAILURE); - } + memset(&nls, 0, sizeof(nls)); + nls.nl_family = AF_NETLINK; + nls.nl_pid = getpid(); + nls.nl_groups = -1; + + fds.events = POLLIN; + fds.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (fds.fd < 0) + edie("socket"); + + if (bind(fds.fd, (void *)&nls, sizeof(nls))) + edie("bind"); + + buf[sizeof(buf)-1] = '\0'; + while (poll(&fds, 1, -1) > -1) { + len = recv(fds.fd, buf, sizeof(buf)-1, MSG_DONTWAIT); + if (len < 0) + edie("recv"); + + if (strstr(buf, "libudev")) { + if (!showudev) + continue; + } else { + if (!showkernel) + continue; + } - mon = udev_monitor_new_from_netlink(udev, rtlink); - if (filter != NULL) - udev_monitor_filter_add_match_subsystem_devtype(mon, \ - filter, NULL); - udev_monitor_enable_receiving(mon); - - fds[0].fd = udev_monitor_get_fd(mon); - fds[0].events = POLLIN|POLLPRI; - - for(;;) { - ret = poll(fds, 1, -1); - if (ret > 0) { - if ((fds[0].revents & POLLIN) \ - || (fds[0].revents & POLLPRI)) { - dev = udev_monitor_receive_device(mon); - if (dev) { - printdevice(dev); - if (doprops) - printproperties(dev); - if (dotags) - printtags(dev); - if (dolinks) - printdevlinks(dev); - printf("\n"); - fflush(stdout); - udev_device_unref(dev); - } + for (i = 0, olen = 0; i < len; i += slen + 1) { + slen = strlen(buf+i); + if (!slen || !strchr(buf+i, '=')) + continue; + if (subsystem && !strncmp(buf+i, "SUBSYSTEM=", 10) + && !strstr(buf+i+10, subsystem)) { + olen = 0; + break; } + + snprintf(obuf+olen, sizeof(obuf)-olen-2, + "%s\n", buf+i); + olen += slen + 1; + } + if (olen > 0) { + obuf[olen] = '\n'; + write(0, obuf, olen+1); } } - exit(EXIT_SUCCESS); + exit(0); }