commit da6383d0b4d1c2843dba3115c7cadfa8137c158c
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sat, 26 Feb 2011 17:20:49 +0100
Initial commit of nlmon.
Diffstat:
| LICENSE | | | 21 | +++++++++++++++++++++ | 
| Makefile | | | 50 | ++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| README.md | | | 11 | +++++++++++ | 
| arg.h | | | 19 | +++++++++++++++++++ | 
| config.mk | | | 23 | +++++++++++++++++++++++ | 
| nlmon.c | | | 167 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
6 files changed, 291 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT/X Consortium License
+
+© 2011 Christoph Lohmann <20h@r-36.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,50 @@
+# nlmon - dynamic window manager
+# See LICENSE file for copyright and license details.
+
+include config.mk
+
+SRC = ${NAME}.c
+OBJ = ${SRC:.c=.o}
+
+all: options ${NAME}
+
+options:
+	@echo ${NAME} build options:
+	@echo "CFLAGS   = ${CFLAGS}"
+	@echo "LDFLAGS  = ${LDFLAGS}"
+	@echo "CC       = ${CC}"
+
+.c.o:
+	@echo CC $<
+	@${CC} -c ${CFLAGS} $<
+
+${OBJ}: config.mk
+
+${NAME}: ${OBJ}
+	@echo CC -o $@
+	@${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+clean:
+	@echo cleaning
+	@rm -f ${NAME} ${OBJ} ${NAME}-${VERSION}.tar.gz
+
+dist: clean
+	@echo creating dist tarball
+	@mkdir -p ${NAME}-${VERSION}
+	@cp -R LICENSE Makefile README.md config.mk \
+		${SRC} *.h ${NAME}-${VERSION}
+	@tar -cf ${NAME}-${VERSION}.tar ${NAME}-${VERSION}
+	@gzip ${NAME}-${VERSION}.tar
+	@rm -rf ${NAME}-${VERSION}
+
+install: all
+	@echo installing executable file to ${DESTDIR}${PREFIX}/bin
+	@mkdir -p ${DESTDIR}${PREFIX}/bin
+	@cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
+	@chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
+
+uninstall:
+	@echo removing executable file from ${DESTDIR}${PREFIX}/bin
+	@rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
+
+.PHONY: all options clean dist install uninstall
diff --git a/README.md b/README.md
@@ -0,0 +1,11 @@
+# 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/arg.h b/arg.h
@@ -0,0 +1,19 @@
+#ifndef ARG_H
+#define ARG_H
+
+#define USED(x) ((void)(x))	
+
+extern char *argv0;
+
+#define	ARGBEGIN	for(argv0 = *argv, argv++, argc--;\
+			    argv[0] && argv[0][0]=='-' && argv[0][1];\
+			    argc--, argv++) {\
+				char _argc;\
+				_argc = argv[0][1];\
+				switch(_argc)
+#define	ARGEND		USED(_argc);} USED(argv);USED(argc);
+#define	EARGF(x)	((argv[1] == NULL)? ((x), abort(), (char *)0) :\
+			(argc--, argv++, argv[0]))
+
+#endif
+
diff --git a/config.mk b/config.mk
@@ -0,0 +1,23 @@
+# nlmon metadata
+NAME = nlmon
+VERSION = 0.2
+
+# Customize below to fit your system
+
+# paths
+PREFIX = /usr
+MANPREFIX = ${PREFIX}/share/man
+
+# includes and libs
+INCS = -I. -I/usr/include
+LIBS = -L/usr/lib -lc -ludev
+
+# flags
+CPPFLAGS = -DVERSION=\"${VERSION}\"
+CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
+LDFLAGS = -g ${LIBS}
+#LDFLAGS = -s ${LIBS}
+
+# compiler and linker
+CC = cc
+
diff --git a/nlmon.c b/nlmon.c
@@ -0,0 +1,167 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libudev.h>
+#include <poll.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "arg.h"
+
+char *argv0;
+
+void
+printdevice(struct udev_device *dev)
+{
+	char *s;
+
+#define PRINTELEM(NAME) \
+	s = (char *)udev_device_get_##NAME(dev); \
+	if (s != NULL) \
+		printf(#NAME "=%s\n", udev_device_get_##NAME(dev));
+
+	PRINTELEM(devpath)
+	PRINTELEM(subsystem)
+	PRINTELEM(devtype)
+	PRINTELEM(syspath)
+	PRINTELEM(sysnum)
+	PRINTELEM(devnode)
+	PRINTELEM(driver)
+
+	printf("devnum=%d\n", (int)udev_device_get_devnum(dev));
+
+	PRINTELEM(action)
+	fflush(stdout);
+}
+
+void
+printproperties(struct udev_device *dev)
+{
+	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);
+}
+
+void
+printtags(struct udev_device *dev)
+{
+	struct udev_list_entry *tags, *tag;
+
+	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);
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "usage: %s [-ptl] [-ku] [-f filter]\n", argv0);
+	fflush(stderr);
+	exit(EXIT_FAILURE);
+}
+
+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";
+
+	ARGBEGIN {
+	case 'f':
+		filter = EARGF(usage());
+		break;
+	case 'p':
+		doprops = 1;
+		break;
+	case 'l':
+		dolinks = 1;
+		break;
+	case 't':
+		dotags = 1;
+		break;
+	case 'k':
+		rtlink = "kernel";
+		break;
+	case 'u':
+		rtlink = "udev";
+		break;
+	default:
+		usage();
+	} ARGEND;
+
+	udev = udev_new();
+	if (!udev) {
+		perror("udev_new");
+		exit(EXIT_FAILURE);
+	}
+
+	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, 500);	
+		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);
+				}
+			}
+		}
+	}
+
+	exit(EXIT_SUCCESS);
+}
+