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);
 }