chiark / gitweb /
[PATCH] Add Red Hat rules and permissions files
[elogind.git] / udevstart.c
1 /*
2  * udevstart.c
3  *
4  * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
5  * 
6  * Quick and dirty way to populate a /dev with udev if your system
7  * does not have access to a shell.  Based originally on a patch to udev 
8  * from Harald Hoyer <harald@redhat.com>
9  *
10  *      This program is free software; you can redistribute it and/or modify it
11  *      under the terms of the GNU General Public License as published by the
12  *      Free Software Foundation version 2 of the License.
13  * 
14  *      This program is distributed in the hope that it will be useful, but
15  *      WITHOUT ANY WARRANTY; without even the implied warranty of
16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *      General Public License for more details.
18  * 
19  *      You should have received a copy of the GNU General Public License along
20  *      with this program; if not, write to the Free Software Foundation, Inc.,
21  *      675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <signal.h>
31 #include <dirent.h>
32 #include <sys/wait.h>
33
34 #include "logging.h"
35
36
37 #ifdef LOG
38 unsigned char logname[42];
39 void log_message(int level, const char *format, ...)
40 {
41         va_list args;
42
43         va_start(args, format);
44         vsyslog(level, format, args);
45         va_end(args);
46 }
47 #endif
48
49
50 #define MAX_PATHLEN     1024
51 #define SYSBLOCK        "/sys/block"
52 #define SYSCLASS        "/sys/class"
53
54 static int execute_udev(char *path, char *value, int len)
55 {
56         int retval;
57         int res;
58         int status;
59         int fds[2];
60         pid_t pid;
61         int value_set = 0;
62         char buffer[255];
63         char *pos;
64
65         retval = pipe(fds);
66         if (retval != 0) {
67                 dbg("pipe failed");
68                 return -1;
69         }
70         pid = fork();
71         switch(pid) {
72         case 0:
73                 /* child */
74                 close(STDOUT_FILENO);
75
76                 /* dup write side of pipe to STDOUT */
77                 dup(fds[1]);
78
79                 dbg("executing /sbin/udev '%s'", path);
80                 retval = execl("/sbin/udev", "/sbin/udev", path, NULL);
81
82                 info("execution of '%s' failed", path);
83                 exit(1);
84         case -1:
85                 dbg("fork failed");
86                 return -1;
87         default:
88                 /* parent reads from fds[0] */
89                 close(fds[1]);
90                 retval = 0;
91                 while (1) {
92                         res = read(fds[0], buffer, sizeof(buffer) - 1);
93                         if (res <= 0)
94                                 break;
95                         buffer[res] = '\0';
96                         if (res > len) {
97                                 dbg("result len %d too short", len);
98                                 retval = -1;
99                         }
100                         if (value_set) {
101                                 dbg("result value already set");
102                                 retval = -1;
103                         } else {
104                                 value_set = 1;
105                                 strncpy(value, buffer, len);
106                                 pos = value + strlen(value)-1;
107                                 if (pos[0] == '\n')
108                                         pos[0] = '\0';
109                                 dbg("result is '%s'", value);
110                         }
111                 }
112                 close(fds[0]);
113                 res = wait(&status);
114                 if (res < 0) {
115                         dbg("wait failed result %d", res);
116                         retval = -1;
117                 }
118
119                 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
120                         dbg("exec program status 0x%x", status);
121                         retval = -1;
122                 }
123         }
124         return retval;
125 }
126
127 static int udev_scan(void)
128 {
129         char           *devpath;
130         DIR            *dir;
131         struct dirent  *dent;
132         int             retval = -EINVAL;
133         char scratch[200];
134
135         devpath = "block";
136         dir = opendir(SYSBLOCK);
137         if (dir) {
138                 for (dent = readdir(dir); dent; dent = readdir(dir)) {
139                         char            dirname[MAX_PATHLEN];
140                         DIR            *dir2;
141                         struct dirent  *dent2;
142                         if ((strcmp(dent->d_name, ".") == 0)
143                             || (strcmp(dent->d_name, "..") == 0))
144                                 continue;
145
146                         snprintf(dirname, MAX_PATHLEN, "/block/%s", dent->d_name);
147
148                         setenv("DEVPATH", dirname, 1);
149                         dbg("udev block, 'DEVPATH' = '%s'", dirname);
150                         execute_udev("block", scratch, sizeof(scratch));
151
152                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSBLOCK, dent->d_name);
153
154                         dir2 = opendir(dirname);
155                         if (dir2) {
156                                 for (dent2 = readdir(dir2); dent2; dent2 = readdir(dir2)) {
157                                         char            dirname2[MAX_PATHLEN];
158                                         DIR            *dir3;
159                                         struct dirent  *dent3;
160
161                                         if ((strcmp(dent2->d_name, ".") == 0) ||
162                                             (strcmp(dent2->d_name, "..") == 0))
163                                                 continue;
164
165                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
166
167                                         dir3 = opendir(dirname2);
168                                         if (dir3) {
169                                                 for (dent3 = readdir(dir3); dent3; dent3 = readdir(dir3)) {
170                                                         char filename[MAX_PATHLEN];
171
172                                                         if (strcmp(dent3->d_name, "dev") == 0) {
173                                                                 snprintf(filename, MAX_PATHLEN, "/block/%s/%s", dent->d_name, dent2->d_name);
174                                                                 setenv("DEVPATH", filename, 1);
175                                                                 dbg("udev block, 'DEVPATH' = '%s'", filename);
176                                                                 execute_udev("block", scratch, sizeof(scratch));
177                                                         }
178                                                 }
179                                         }
180                                 }
181                         }
182                 }
183         }
184
185         devpath = "class";
186         dir = opendir(SYSCLASS);
187         if (dir) {
188                 for (dent = readdir(dir); dent; dent = readdir(dir)) {
189                         char            dirname[MAX_PATHLEN];
190                         DIR            *dir2;
191                         struct dirent  *dent2;
192                         if ((strcmp(dent->d_name, ".") == 0)
193                             || (strcmp(dent->d_name, "..") == 0))
194                                 continue;
195
196                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSCLASS, dent->d_name);
197
198                         dir2 = opendir(dirname);
199                         if (dir2) {
200                                 for (dent2 = readdir(dir2); dent2; dent2 = readdir(dir2)) {
201                                         char            dirname2[MAX_PATHLEN];
202                                         DIR            *dir3;
203                                         struct dirent  *dent3;
204
205                                         if ((strcmp(dent2->d_name, ".") == 0) || (strcmp(dent2->d_name, "..") == 0))
206                                                 continue;
207
208                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
209
210                                         dir3 = opendir(dirname2);
211                                         if (dir3) {
212                                                 for (dent3 = readdir(dir3); dent3; dent3 = readdir(dir3)) {
213                                                         char
214                                                                         filename[MAX_PATHLEN];
215
216                                                         if (strcmp(dent3->d_name, "dev") == 0) {
217                                                                 snprintf
218                                                                     (filename,
219                                                                      MAX_PATHLEN,
220                                                                      "/class/%s/%s", dent->d_name, dent2->d_name);
221                                                                 setenv("DEVPATH", filename, 1);
222                                                                 dbg("udev '%s', 'DEVPATH' = '%s'", dent->d_name, filename);
223                                                                 execute_udev(dent->d_name, scratch, sizeof(scratch));
224                                                         }
225                                                 }
226                                         }
227                                 }
228                         }
229                 }
230         }
231
232         if (retval > 0)
233                 retval = 0;
234
235         return -retval;
236 }
237
238
239 int main(int argc, char **argv, char **envp)
240 {
241         init_logging("udevstart");
242
243         setenv("ACTION", "add", 1);
244         setenv("UDEV_NO_SLEEP", "1", 1);
245
246         return udev_scan();
247 }