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