nlmon

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

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