nltrigger.c - 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) README
 (DIR) 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