nldev

NetLink DEVice manager; a lightweight netlink frontend for mdev.
git clone git://r-36.net/nldev
Log | Files | Refs | README | LICENSE

nltrigger.c (2463B)


      1 /* See LICENSE file for copyright. */
      2 /*
      3  * Based on smdev -s code. Thanks for the prework!
      4  */
      5 #include <dirent.h>
      6 #include <errno.h>
      7 #include <fcntl.h>
      8 #include <stdarg.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 #include <unistd.h>
     13 #include <sys/stat.h>
     14 
     15 #include "arg.h"
     16 
     17 char *argv0;
     18 static void venprintf(int, const char *, va_list);
     19 
     20 void
     21 eprintf(const char *fmt, ...)
     22 {
     23 	va_list ap;
     24 
     25 	va_start(ap, fmt);
     26 	venprintf(EXIT_FAILURE, fmt, ap);
     27 	va_end(ap);
     28 }
     29 
     30 void
     31 enprintf(int status, const char *fmt, ...)
     32 {
     33 	va_list ap;
     34 
     35 	va_start(ap, fmt);
     36 	venprintf(status, fmt, ap);
     37 	va_end(ap);
     38 }
     39 
     40 void
     41 venprintf(int status, const char *fmt, va_list ap)
     42 {
     43 	vfprintf(stderr, fmt, ap);
     44 
     45 	if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
     46 		fputc(' ', stderr);
     47 		perror(NULL);
     48 	}
     49 
     50 	exit(status);
     51 }
     52 
     53 void
     54 apathmax(char **p, long *size)
     55 {
     56 	errno = 0;
     57 
     58 	if((*size = pathconf("/", _PC_PATH_MAX)) == -1) {
     59 		if(errno == 0) {
     60 			*size = BUFSIZ;
     61 		} else {
     62 			eprintf("pathconf:");
     63 		}
     64 	}
     65 
     66 	if(!(*p = malloc(*size)))
     67 		eprintf("malloc:");
     68 }
     69 
     70 char *
     71 agetcwd(void)
     72 {
     73 	char *buf;
     74 	long size;
     75 
     76 	apathmax(&buf, &size);
     77 	if(!getcwd(buf, size))
     78 		eprintf("getcwd:");
     79 
     80 	return buf;
     81 }
     82 
     83 void
     84 recurse(char *path, char *action, useconds_t delay,
     85 		void (*fn)(char *, char *, useconds_t))
     86 {
     87 	char *cwd;
     88 	struct dirent *d;
     89 	struct stat st;
     90 	DIR *dp;
     91 
     92 	if(lstat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
     93 		return;
     94 	} else if(!(dp = opendir(path))) {
     95 		eprintf("opendir %s:", path);
     96 	}
     97 
     98 	cwd = agetcwd();
     99 	if(chdir(path) == -1)
    100 		eprintf("chdir %s:", path);
    101 
    102 	while((d = readdir(dp))) {
    103 		if(strcmp(d->d_name, ".") && strcmp(d->d_name, ".."))
    104 			fn(d->d_name, action, delay);
    105 	}
    106 
    107 	closedir(dp);
    108 	if(chdir(cwd) == -1)
    109 		eprintf("chdir %s:", cwd);
    110 
    111 	free(cwd);
    112 }
    113 
    114 void
    115 trigger(char *path, char *action, useconds_t delay)
    116 {
    117 	int fd;
    118 
    119 	recurse(path, action, delay, trigger);
    120 	if (strstr(path, "uevent")) {
    121 		if ((fd = open("uevent", O_WRONLY | O_CLOEXEC)) != -1) {
    122 			dprintf(fd, "%s\n", action);
    123 			close(fd);
    124 			usleep(delay);
    125 		}
    126 	}
    127 }
    128 
    129 void
    130 usage(void)
    131 {
    132 	eprintf("usage: %s path [add|list|del|action] [delay]\n", argv0);
    133 }
    134 
    135 int
    136 main(int argc, char *argv[])
    137 {
    138 	char *path = NULL, *action = "add";
    139 	static useconds_t delay = 1000;
    140 
    141 	ARGBEGIN {
    142 	default:
    143 		usage();
    144 	} ARGEND;
    145 
    146 	if (argc == 0)
    147 		usage();
    148 
    149 	path = argv[0];
    150 	argc--; argv++;
    151 	if (argc > 0) {
    152 		action = argv[0];
    153 		argc--; argv++;
    154 	}
    155 	if (argc > 0)
    156 		delay = atol(argv[0]);
    157 
    158 	trigger(path, action, delay);
    159 
    160 	return 0;
    161 }
    162