1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "log.h"
#define EVENT_TIMEOUT 2000
void
child(char *runpath)
{
pid_t pid;
if (!(pid = fork())) {
dbg("running %s", runpath);
if (execlp(runpath, basename(runpath), NULL) < 0)
edie("execvp");
exit(0);
}
if (pid < 0)
edie("fork");
waitpid(pid, NULL, 0);
}
void
usage(void)
{
die("usage: %s [-d] [-r run]\n", argv0);
}
int main(int argc, char *argv[])
{
struct pollfd fds;
int r;
static char buf[16384];
char *runpath = "/bin/mdev";
char *subsystem = NULL;
ARGBEGIN {
case 'd':
dodebug = 1;
break;
case 'r':
runpath = EARGF(usage());
break;
case 'f':
subsystem = EARGF(usage());
break;
default:
usage();
} ARGEND;
dbg("runpath=%s\n", runpath);
fds.fd = 0; /* stdin */
fds.events = POLLIN;
while ((r = poll(&fds, 1, EVENT_TIMEOUT)) > 0) {
size_t len;
int i, slen;
char *key, *value;
clearenv();
setenv("PATH", "/sbin:/bin", 1);
if (!(fds.revents & POLLIN))
continue;
len = read(fds.fd, buf, sizeof(buf)-1);
buf[len] = 0;
dbg("Got %u bytes", len);
slen = 0;
for (i = 0; i < len; i += slen + 1) {
key = buf + i;
value = strchr(key, '=');
slen = strlen(buf+i);
if (!slen || value == NULL)
continue;
if (subsystem && !strncmp(key, "SUBSYSTEM=", 10)
&& !strstr(key+10, subsystem)) {
dbg("subsystem filter '%s' applied.",
subsystem);
break;
}
value[0] = '\0';
value++;
/*
* We generally trust the kernel. But there
* might be some udev flaw. (It's >20k sloc!)
*/
if (strcmp(key, "PATH")) {
setenv(key, value, 1);
dbg("%s = \"%s\"", key, value);
}
}
if (getenv("ACTION") != NULL &&
getenv("DEVPATH") != NULL &&
getenv("SUBSYSTEM") != NULL &&
getenv("SEQNUM") != NULL) {
child(runpath);
}
if (fds.revents & POLLHUP) {
dbg("parent hung up\n");
return 0;
}
}
if (r == -1)
edie("poll");
if (r == 0)
dbg("exit due to timeout");
return 0;
}
|