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