tPush v0.4 with major changes. - nldev - NetLink DEVice manager; a lightweight netlink frontend for mdev.
 (HTM) git clone git://r-36.net/nldev
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 1953099f5f153e6e6bb19db54bd334bc25e6f655
 (DIR) parent b30694187cbd260d08dfc38dd468d41938d5bff9
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Sun, 12 Sep 2021 20:59:58 +0200
       
       Push v0.4 with major changes.
       
       * nltrigger in C instead of old script
       * nltrigger.1 manpage
       * make now follows bitreich simpler output rules
       * there is now a config.h with selection of when to trigger commands
               * this filters and speeds up the whole system init
       
       Thanks Platon Ryzhikov <ihummer63@yandex.ru> for sending in
       tthe proposal and giving me the motivation to renew nldev
       tto this stage.
       
       Diffstat:
         Makefile                            |      72 ++++++++++++++-----------------
         config.mk                           |       6 +++---
         nldev.c                             |      37 ++++++++++++++++++-------------
         nltrigger                           |      83 -------------------------------
         nltrigger.1                         |      48 +++++++++++++++++++++++++++++++
         nltrigger.c                         |     160 +++++++++++++++++++++++++++++++
       
       6 files changed, 265 insertions(+), 141 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -3,20 +3,13 @@
        
        include config.mk
        
       -SRC = ${NAME}.c
       +SRC = ${NAME}.c nltrigger.c
        OBJ = ${SRC:.c=.o}
        
       -all: options ${NAME}
       -
       -options:
       -        @echo ${NAME} build options:
       -        @echo "CFLAGS   = ${CFLAGS}"
       -        @echo "LDFLAGS  = ${LDFLAGS}"
       -        @echo "CC       = ${CC}"
       +all: ${NAME} nltrigger
        
        .c.o:
       -        @echo CC $<
       -        @${CC} -c ${CFLAGS} $<
       +        ${CC} -c ${CFLAGS} $<
        
        ${OBJ}: config.h config.mk
        
       t@@ -24,40 +17,41 @@ config.h:
                cp config.def.h $@
        
        ${NAME}: ${OBJ}
       -        @echo CC -o $@
       -        @${CC} -o $@ ${OBJ} ${LDFLAGS}
       +        ${CC} -o $@ $@.o ${LDFLAGS}
       +
       +nltrigger: ${OBJ}
       +        ${CC} -o $@ $@.o ${LDFLAGS}
       +
        
        clean:
       -        @echo cleaning
       -        @rm -f ${NAME} ${OBJ} ${NAME}-${VERSION}.tar.gz
       +        rm -f ${NAME} ${OBJ} nltrigger ${NAME}-${VERSION}.tar.gz
        
        dist: clean
       -        @echo creating dist tarball
       -        @mkdir -p ${NAME}-${VERSION}
       -        @cp -R LICENSE Makefile README.md FIXES.md config.def.h config.mk \
       -                ${SRC} ${NAME}.8 *.h ${NAME}-${VERSION}
       -        @tar -cf ${NAME}-${VERSION}.tar ${NAME}-${VERSION}
       -        @gzip ${NAME}-${VERSION}.tar
       -        @rm -rf ${NAME}-${VERSION}
       +        mkdir -p ${NAME}-${VERSION}
       +        cp -R LICENSE Makefile README.md FIXES.md config.def.h config.mk \
       +                ${SRC} ${NAME}.8 nltrigger.1 *.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
       -        @cp -f run_${NAME} ${DESTDIR}${PREFIX}/bin
       -        @cp -f nltrigger ${DESTDIR}${PREFIX}/bin
       -        @chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
       -        @echo installing manual page to ${DESTDIR}${MANPREFIX}/man8
       -        @mkdir -p ${DESTDIR}${MANPREFIX}/man8
       -        @cp -f ${NAME}.8 ${DESTDIR}${MANPREFIX}/man8
       -        @chmod 644 ${DESTDIR}${MANPREFIX}/man8/${NAME}.8
       +        mkdir -p ${DESTDIR}${PREFIX}/bin
       +        cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
       +        cp -f run_${NAME} ${DESTDIR}${PREFIX}/bin
       +        cp -f nltrigger ${DESTDIR}${PREFIX}/bin
       +        chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
       +        mkdir -p ${DESTDIR}${MANPREFIX}/man8
       +        cp -f ${NAME}.8 ${DESTDIR}${MANPREFIX}/man8
       +        chmod 644 ${DESTDIR}${MANPREFIX}/man8/${NAME}.8
       +        mkdir -p ${DESTDIR}${MANPREFIX}/man1
       +        cp -f nltrigger.1 ${DESTDIR}${MANPREFIX}/man1
       +        chmod 644 ${DESTDIR}${MANPREFIX}/man1/nltrigger.1
        
        uninstall:
       -        @echo removing executable file from ${DESTDIR}${PREFIX}/bin
       -        @rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
       -        @rm -f ${DESTDIR}${PREFIX}/bin/run_${NAME}
       -        @rm -f ${DESTDIR}${PREFIX}/bin/nltrigger
       -        @echo removing manual page from ${DESTDIR}${PREFIX}/man8
       -        @rm -f ${DESTDIR}${MANPREFIX}/man8/${NAME}.8
       -
       -.PHONY: all options clean dist install uninstall
       +        rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
       +        rm -f ${DESTDIR}${PREFIX}/bin/run_${NAME}
       +        rm -f ${DESTDIR}${PREFIX}/bin/nltrigger
       +        rm -f ${DESTDIR}${MANPREFIX}/man8/${NAME}.8
       +        rm -f ${DESTDIR}${MANPREFIX}/man1/nltrigger.1
       +
       +.PHONY: all clean dist install uninstall
 (DIR) diff --git a/config.mk b/config.mk
       t@@ -1,6 +1,6 @@
        # nldev metadata
        NAME = nldev
       -VERSION = 0.3
       +VERSION = 0.4
        
        # Customize below to fit your system
        
       t@@ -14,8 +14,8 @@ LIBS = -L/usr/lib -lc
        
        # flags
        CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -D_GNU_SOURCE
       -CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
       -LDFLAGS = -static -g ${LIBS}
       +CFLAGS = -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
       +LDFLAGS = -static ${LIBS}
        #LDFLAGS = -s ${LIBS}
        
        # compiler and linker
 (DIR) diff --git a/nldev.c b/nldev.c
       t@@ -1,7 +1,4 @@
       -/*
       - * Copy me if you can.
       - * by 20h
       - */
       +/* See LICENSE for copyright information. */
        
        #include <unistd.h>
        #include <stdio.h>
       t@@ -22,10 +19,10 @@
        #include <linux/netlink.h>
        
        typedef struct {
       -        const char *action; /* ACTION to run rule for */
       -        const char *subsystem; /* SUBSYSTEM to run the rule for, NULL for any */
       -        const char *envvar; /* other environment variable to run rule for, NULL for any */
       -        const char *runpath;
       +        char *action; /* ACTION to run rule for */
       +        char *subsystem; /* SUBSYSTEM to run the rule for, NULL for any */
       +        char *envvar; /* other environment variable to run rule for, NULL for any */
       +        char *runpath;
        } Rule;
        
        #include "arg.h"
       t@@ -336,20 +333,28 @@ main(int argc, char *argv[])
                                        getenv("DEVPATH") != NULL &&
                                        getenv("SUBSYSTEM") != NULL &&
                                        getenv("SEQNUM") != NULL) {
       -                        if (runpath)
       +                        if (runpath) {
                                        child(runpath);
       -                        else {
       +                        } else {
                                        for (i = 0; i < LENGTH(rules); i+=1) {
       -                                        if (rules[i].action == NULL || rules[i].runpath == NULL) /* rule must have non-NULL action and runpath */
       +                                        if (rules[i].action == NULL
       +                                                        || rules[i].runpath == NULL) {
                                                        continue;
       -                                        if (strcmp(getenv("ACTION"), rules[i].action))
       +                                        }
       +                                        if (strcmp(getenv("ACTION"), rules[i].action)) {
                                                        continue;
       -                                        if (rules[i].subsystem != NULL)
       -                                                if (strcmp(getenv("SUBSYSTEM"), rules[i].subsystem))
       +                                        }
       +                                        if (rules[i].subsystem != NULL) {
       +                                                if (strcmp(getenv("SUBSYSTEM"),
       +                                                                rules[i].subsystem)) {
                                                                continue;
       -                                        if (rules[i].envvar != NULL)
       -                                                if (getenv(rules[i].envvar) == NULL)
       +                                                }
       +                                        }
       +                                        if (rules[i].envvar != NULL) {
       +                                                if (getenv(rules[i].envvar) == NULL) {
                                                                continue;
       +                                                }
       +                                        }
                                                child(rules[i].runpath);
                                        }
                                }
 (DIR) diff --git a/nltrigger b/nltrigger
       t@@ -1,83 +0,0 @@
       -#!/bin/busybox ash
       -
       -usage() {
       -        printf "usage: %s [add|list|del|action] [subsystem]\n" "$(basename $1)" >&2
       -        exit 1
       -}
       -
       -action="list"
       -if [ $# -gt 0 ];
       -then
       -        action="$1"
       -fi
       -
       -if [ "$action" = "list" ];
       -then
       -        printf "class:\n"
       -        for i in /sys/class/*;
       -        do
       -                printf "\t%s\n" $(basename $i)
       -        done
       -
       -        printf "bus:\n"
       -        for i in /sys/bus/*;
       -        do
       -                printf "\t%s\n" $(basename $i)
       -        done
       -
       -        printf "devices:\n"
       -        for i in /sys/devices/*;
       -        do
       -                printf "\t%s\n" $(basename $i)
       -        done
       -
       -        exit 0
       -fi
       -
       -if [ $# -lt 2 ];
       -then
       -        usage "$0"
       -fi
       -subsystem="$2"
       -
       -if [ "$subsystem" != "all" ];
       -then
       -        if [ -d /sys/class/$subsystem ];
       -        then
       -                for i in /sys/class/$subsystem/*/uevent;
       -                do
       -                        echo $action > $i
       -                done
       -                exit 0
       -        fi
       -
       -        if [ -d /sys/bus/$subsystem ];
       -        then
       -                for i in /sys/bus/$subsystem/devices/*/uevent;
       -                do
       -                        echo $action > $i
       -                done
       -                exit 0
       -        fi
       -
       -        if [ -d /sys/devices/$subsystem ];
       -        then
       -                for i in /sys/devices/$subsystem/*/uevent \
       -                        /sys/devices/$subsystem/*/*/uevent;
       -                do
       -                        echo $action > $i
       -                done
       -                exit 0
       -        fi
       -
       -        printf "Could not find subsystem '%s'.\n" $i >&2
       -        exit 1
       -fi
       -
       -for i in $(find /sys -name uevent -print | sed -e 's/ /,/g');
       -do
       -        echo $action > "$(echo $i | sed -e 's/,/ /g')"
       -done
       -
       -exit 0
       -
 (DIR) diff --git a/nltrigger.1 b/nltrigger.1
       t@@ -0,0 +1,48 @@
       +.Dd September 12, 2021
       +.Dt NLTRIGGER 1
       +.Os
       +.
       +.Sh NAME
       +.Nm nltrigger
       +.Nd a tool to trigger netlink device events
       +.
       +.Sh SYNOPSIS
       +.Nm
       +.Bk -words
       +.Ar path
       +.Op Ar add|list|del|action
       +.Op Ar delay
       +.Ek
       +.
       +.Sh DESCRIPTION
       +.Bd -filled
       +.Nm
       +is a simple tool to trigger netlink device events at a certain
       +.Ar path
       +with a certain
       +.Ar action
       +and a certain
       +.Ar delay.
       +. 
       +.Sh OPTIONS
       +.Pp
       +.Bl -tag -width Ds
       +.Ar Path
       +to be used as target.
       +.Ar Action
       +of [add|list|del|action]
       +should be triggered.
       +.Ar Delay
       +of usecs to wait after the
       +.Ar action
       +has been triggered.
       +(Default is 1000 usecs.)
       +.El
       +.Sh AUTHORS
       +See the LICENSE file for the authors of this software.
       +.
       +.Sh LICENSE
       +.Nm
       +is released under the MIT/X Consortium License.
       +.
       +
 (DIR) diff --git a/nltrigger.c b/nltrigger.c
       t@@ -0,0 +1,160 @@
       +/* See LICENSE file for copyright. */
       +/*
       + * Based on smdev -s code. Thanks for the prework!
       + */
       +#include <dirent.h>
       +#include <errno.h>
       +#include <fcntl.h>
       +#include <stdarg.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <unistd.h>
       +#include <sys/stat.h>
       +
       +#include "arg.h"
       +
       +char *argv0;
       +static char *action = "add";
       +static useconds_t delay = 1000;
       +static void venprintf(int, const char *, va_list);
       +
       +void
       +eprintf(const char *fmt, ...)
       +{
       +        va_list ap;
       +
       +        va_start(ap, fmt);
       +        venprintf(EXIT_FAILURE, fmt, ap);
       +        va_end(ap);
       +}
       +
       +void
       +enprintf(int status, const char *fmt, ...)
       +{
       +        va_list ap;
       +
       +        va_start(ap, fmt);
       +        venprintf(status, fmt, ap);
       +        va_end(ap);
       +}
       +
       +void
       +venprintf(int status, const char *fmt, va_list ap)
       +{
       +        vfprintf(stderr, fmt, ap);
       +
       +        if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
       +                fputc(' ', stderr);
       +                perror(NULL);
       +        }
       +
       +        exit(status);
       +}
       +
       +void
       +apathmax(char **p, long *size)
       +{
       +        errno = 0;
       +
       +        if((*size = pathconf("/", _PC_PATH_MAX)) == -1) {
       +                if(errno == 0) {
       +                        *size = BUFSIZ;
       +                } else {
       +                        eprintf("pathconf:");
       +                }
       +        }
       +
       +        if(!(*p = malloc(*size)))
       +                eprintf("malloc:");
       +}
       +
       +char *
       +agetcwd(void)
       +{
       +        char *buf;
       +        long size;
       +
       +        apathmax(&buf, &size);
       +        if(!getcwd(buf, size))
       +                eprintf("getcwd:");
       +
       +        return buf;
       +}
       +
       +void
       +recurse(const char *path, void (*fn)(const char *))
       +{
       +        char *cwd;
       +        struct dirent *d;
       +        struct stat st;
       +        DIR *dp;
       +
       +        if(lstat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
       +                return;
       +        } else if(!(dp = opendir(path))) {
       +                eprintf("opendir %s:", path);
       +        }
       +
       +        cwd = agetcwd();
       +        if(chdir(path) == -1)
       +                eprintf("chdir %s:", path);
       +
       +        while((d = readdir(dp))) {
       +                if(strcmp(d->d_name, ".") && strcmp(d->d_name, ".."))
       +                        fn(d->d_name);
       +        }
       +
       +        closedir(dp);
       +        if(chdir(cwd) == -1)
       +                eprintf("chdir %s:", cwd);
       +
       +        free(cwd);
       +}
       +
       +void
       +trigger(const char *path)
       +{
       +        int fd;
       +
       +        recurse(path, trigger);
       +        if (strstr(path, "uevent")) {
       +                if ((fd = open("uevent", O_WRONLY | O_CLOEXEC)) != -1) {
       +                        dprintf(fd, "%s\n", action);
       +                        close(fd);
       +                        usleep(delay);
       +                }
       +        }
       +}
       +
       +void usage(void)
       +{
       +        eprintf("usage: %s path [add|list|del|action] [delay]\n", argv0);
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        char *path = NULL;
       +
       +        ARGBEGIN {
       +        default:
       +                usage();
       +        } ARGEND;
       +
       +        if (argc == 0)
       +                usage();
       +
       +        path = argv[0];
       +        if (argc > 0) {
       +                action = argv[0];
       +                argc--; argv++;
       +        }
       +        if (argc > 0)
       +                delay = atol(argv[0]);
       +
       +        trigger(path);
       +
       +        return 0;
       +}
       +