diff options
Diffstat (limited to 'urunlevel/runlevel/lib_init_d.c')
-rw-r--r-- | urunlevel/runlevel/lib_init_d.c | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/urunlevel/runlevel/lib_init_d.c b/urunlevel/runlevel/lib_init_d.c new file mode 100644 index 0000000..866888c --- /dev/null +++ b/urunlevel/runlevel/lib_init_d.c | |||
@@ -0,0 +1,425 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 by David Seikel won_fang@yahoo.com.au | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
17 | * 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <dirent.h> | ||
22 | #include <fcntl.h> | ||
23 | #include <unistd.h> | ||
24 | #include <errno.h> | ||
25 | #include <signal.h> | ||
26 | #include <string.h> | ||
27 | #include <sys/poll.h> | ||
28 | #include <sys/wait.h> | ||
29 | #include <sys/utsname.h> /* for uname(2) */ | ||
30 | |||
31 | #include "busybox.h" | ||
32 | #include "lib_init_d.h" | ||
33 | |||
34 | |||
35 | static char *shell = 0; | ||
36 | struct stat path_stat; | ||
37 | |||
38 | |||
39 | char *argv_cat(int argc, char **argv) | ||
40 | { | ||
41 | int i; | ||
42 | int length = 1; | ||
43 | char *message = NULL; | ||
44 | |||
45 | for (i = 0; i < argc; i++) | ||
46 | length += strlen(argv[i]); | ||
47 | message = (char *) xmalloc(sizeof (char) * length); | ||
48 | |||
49 | if (message != NULL) | ||
50 | { | ||
51 | message[0] = '\0'; | ||
52 | for (i = 1; i < argc; i++) | ||
53 | { | ||
54 | strcat(message, argv[i]); | ||
55 | if (i < (argc - 1)) | ||
56 | strcat(message, " "); | ||
57 | } | ||
58 | } | ||
59 | return message; | ||
60 | } | ||
61 | |||
62 | |||
63 | char *big_chomp(char *s) | ||
64 | { | ||
65 | char *lc = index(s, '\n'); | ||
66 | |||
67 | if(lc) | ||
68 | *lc = '\0'; | ||
69 | return s; | ||
70 | } | ||
71 | |||
72 | |||
73 | char *doit(int mode, char *command, ...) | ||
74 | { | ||
75 | int buffsize = 63; | ||
76 | char *buffer = NULL; | ||
77 | int dataPipe[2] = { -1, -1 }; | ||
78 | int statusPipe[2] = { -1, -1 }; | ||
79 | int n; | ||
80 | pid_t pid = 0; | ||
81 | volatile int vfork_exec_errno = 0; | ||
82 | char **args; | ||
83 | char *commandBuffer; | ||
84 | |||
85 | if (mode & DAEMON) | ||
86 | mode |= FORK | QUIET; | ||
87 | |||
88 | va_list p; | ||
89 | int r; | ||
90 | |||
91 | va_start(p, command); | ||
92 | r = vasprintf(&commandBuffer, command, p); | ||
93 | va_end(p); | ||
94 | |||
95 | if (r < 0) | ||
96 | bb_perror_msg_and_die("doit"); | ||
97 | |||
98 | if (shell == 0) | ||
99 | { | ||
100 | shell = getenv("SHELL"); | ||
101 | if (shell == 0) | ||
102 | shell = "/bin/sh"; | ||
103 | } | ||
104 | |||
105 | args = (char **) xmalloc (sizeof (char *) * 4); | ||
106 | n = 0; | ||
107 | args[n++] = shell; | ||
108 | args[n++] = "-c"; | ||
109 | if (mode & QUIET) | ||
110 | bb_xasprintf(&(args[n++]), "%s 2>/dev/null", commandBuffer); | ||
111 | else | ||
112 | args[n++] = commandBuffer; | ||
113 | args[n++] = 0; | ||
114 | |||
115 | if (!(mode & NOFORK)) | ||
116 | { | ||
117 | if (!(mode & DAEMON)) | ||
118 | { | ||
119 | if (pipe(dataPipe) < 0 || pipe(statusPipe) < 0) | ||
120 | bb_perror_msg("Failed to create pipe"); | ||
121 | signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ | ||
122 | } | ||
123 | // pid = vfork(); | ||
124 | pid = fork(); | ||
125 | } | ||
126 | if (pid == 0) /* child */ | ||
127 | { | ||
128 | if ((!(mode & NOFORK)) && (!(mode & NOFORK))) | ||
129 | { | ||
130 | close(STDIN_FILENO); | ||
131 | dup2(dataPipe[1], STDOUT_FILENO); | ||
132 | dup2(dataPipe[1], STDERR_FILENO); | ||
133 | close(dataPipe[0]); | ||
134 | close(statusPipe[0]); | ||
135 | fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows sucess */ | ||
136 | } | ||
137 | |||
138 | if ((mode & DAEMON)) | ||
139 | { | ||
140 | if (!(mode & NOFORK)) | ||
141 | { | ||
142 | close(dataPipe[1]); | ||
143 | close(statusPipe[1]); | ||
144 | close(STDOUT_FILENO); | ||
145 | close(STDERR_FILENO); | ||
146 | } | ||
147 | daemon(1, 0); | ||
148 | } | ||
149 | errno = 0; | ||
150 | execvp(shell, (char **) args ); | ||
151 | |||
152 | vfork_exec_errno = errno; | ||
153 | if (!(mode & NOFORK)) | ||
154 | close(statusPipe[1]); | ||
155 | _exit(-1); | ||
156 | } | ||
157 | else if (pid > 0) /* parent */ | ||
158 | { | ||
159 | close(dataPipe[1]); | ||
160 | close(statusPipe[1]); | ||
161 | |||
162 | while (1) | ||
163 | { | ||
164 | char buf; | ||
165 | |||
166 | n = read(statusPipe[0], &buf, 1); | ||
167 | |||
168 | if ((n < 0) && ((errno == EAGAIN) || (errno == EINTR)) && !(mode & FORK)) | ||
169 | continue; /* try it again */ | ||
170 | else if (n == 0 && vfork_exec_errno != 0) | ||
171 | { | ||
172 | errno = vfork_exec_errno; | ||
173 | bb_perror_msg("Could not exec process"); | ||
174 | } | ||
175 | break; | ||
176 | } | ||
177 | close(statusPipe[0]); | ||
178 | |||
179 | if (buffer == NULL) | ||
180 | buffer = (char *) xcalloc(buffsize + 1, sizeof (char)); | ||
181 | |||
182 | if ((mode & FORK) == 0) | ||
183 | { | ||
184 | ssize_t cc; | ||
185 | struct pollfd poller[1]; | ||
186 | |||
187 | poller[0].fd = dataPipe[0]; | ||
188 | poller[0].events = POLLIN | POLLPRI; | ||
189 | poller[0].revents = 0; | ||
190 | |||
191 | n = 0; | ||
192 | while (1) | ||
193 | { | ||
194 | if ((buffsize - n) <= 0) | ||
195 | { | ||
196 | int i; | ||
197 | |||
198 | buffsize += buffsize; | ||
199 | buffer = xrealloc(buffer, sizeof(char) * (buffsize + 1)); | ||
200 | for (i = n; i <= buffsize; i++) | ||
201 | buffer[i] = '\0'; | ||
202 | } | ||
203 | |||
204 | errno = 0; | ||
205 | cc = poll(poller, 1, 1010); /* network sleeps for 1000 between '.' outputs */ | ||
206 | if (cc > 0) | ||
207 | cc = read(dataPipe[0], &buffer[n], buffsize - n); | ||
208 | |||
209 | if (cc < 0) | ||
210 | { | ||
211 | if (errno == EINTR) | ||
212 | continue; | ||
213 | if (errno == EAGAIN) | ||
214 | continue; | ||
215 | break; | ||
216 | } | ||
217 | else if (cc == 0) | ||
218 | break; | ||
219 | |||
220 | if ((mode & (QUIET | REDIR)) == 0) | ||
221 | bb_printf(&buffer[n]); | ||
222 | n += cc; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | if (mode & REDIR) | ||
227 | chomp(buffer); | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | bb_perror_msg("Failed to fork process"); | ||
232 | } | ||
233 | |||
234 | n = 0; | ||
235 | if (pid) | ||
236 | { | ||
237 | close(dataPipe[0]); | ||
238 | |||
239 | if ((mode & FORK) == 0) | ||
240 | { | ||
241 | if (waitpid(pid, &n, 0) == -1) | ||
242 | bb_printf("Couldn't wait?"); | ||
243 | } | ||
244 | if (WIFEXITED(n)) | ||
245 | n = WEXITSTATUS(n); | ||
246 | else | ||
247 | n = -1; | ||
248 | } | ||
249 | |||
250 | free(args); | ||
251 | free(commandBuffer); | ||
252 | errno = n; | ||
253 | return buffer; | ||
254 | } | ||
255 | |||
256 | |||
257 | #ifdef RUNLEVEL_LIST | ||
258 | // From ifupdown, so it should probably be in libbb. | ||
259 | llist_t *llist_add_to_end(llist_t *list_head, char *data) | ||
260 | { | ||
261 | llist_t *new_item, *tmp, *prev; | ||
262 | |||
263 | new_item = xmalloc(sizeof(llist_t)); | ||
264 | new_item->data = data; | ||
265 | new_item->link = NULL; | ||
266 | |||
267 | prev = NULL; | ||
268 | tmp = list_head; | ||
269 | while(tmp) | ||
270 | { | ||
271 | prev = tmp; | ||
272 | tmp = tmp->link; | ||
273 | } | ||
274 | if (prev) | ||
275 | prev->link = new_item; | ||
276 | else | ||
277 | list_head = new_item; | ||
278 | |||
279 | return(list_head); | ||
280 | } | ||
281 | #endif | ||
282 | |||
283 | |||
284 | llist_t *llist_delete(llist_t **head, llist_t *previous, llist_t *current) | ||
285 | { | ||
286 | if (previous == NULL) | ||
287 | { | ||
288 | *head = current->link; | ||
289 | free(current); | ||
290 | current = *head; | ||
291 | } | ||
292 | else | ||
293 | { | ||
294 | previous->link = current->link; | ||
295 | free(current); | ||
296 | current = previous->link; | ||
297 | } | ||
298 | |||
299 | return current; | ||
300 | } | ||
301 | |||
302 | |||
303 | void make_disk(char *token, const nodes_t *nodes) | ||
304 | { | ||
305 | int i; | ||
306 | char temp[32]; | ||
307 | |||
308 | for (i = 0; nodes[i].name != 0; i++) | ||
309 | { | ||
310 | if (strncmp(nodes[i].name, token, 3) == 0) | ||
311 | { | ||
312 | int m = atoi(&token[3]); | ||
313 | sprintf(temp, "/dev/%s", token); | ||
314 | mknod(temp, nodes[i].mode, makedev(nodes[i].major, nodes[i].minor + m)); | ||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | sprintf(temp, "/media/%s", token); | ||
319 | bb_make_directory(temp, -1l, FILEUTILS_RECUR); | ||
320 | } | ||
321 | |||
322 | |||
323 | void make_ram_disk(int size, int number, char *place, int TMPFS) | ||
324 | { | ||
325 | if (size > 0) | ||
326 | { | ||
327 | char *place2; | ||
328 | |||
329 | bb_printf( "Creating ramdisk at %s\n", place); | ||
330 | bb_xasprintf(&place2, "%s2", place); | ||
331 | if (copy_file(place, place2, FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) | ||
332 | remove_file(place, FILEUTILS_RECUR | FILEUTILS_FORCE); | ||
333 | bb_make_directory (place, -1l, 0); | ||
334 | if (TMPFS) | ||
335 | quick_mount("tmpfs", "/dev/null", place, "-n -o size=%i", size * 1024); | ||
336 | else | ||
337 | { | ||
338 | doit(QUIET, "mkfs.minix /dev/ram%i %i", number, size); | ||
339 | quick_mount("minix", "", "", "/dev/ram%i %s", number, place); | ||
340 | } | ||
341 | if (copy_file(place2, place, FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) | ||
342 | remove_file(place2, FILEUTILS_RECUR | FILEUTILS_FORCE); | ||
343 | free(place2); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | |||
348 | void quick_mount(char *type, char *device, char *path, char *data, ...) | ||
349 | { | ||
350 | char *dataBuffer; | ||
351 | va_list p; | ||
352 | int r; | ||
353 | |||
354 | va_start(p, data); | ||
355 | r = vasprintf(&dataBuffer, data, p); | ||
356 | va_end(p); | ||
357 | if (r < 0) | ||
358 | bb_perror_msg("quick_mount"); | ||
359 | else | ||
360 | { | ||
361 | doit(QUIET, "busybox mount -t %s %s %s %s", type, device, path, dataBuffer); | ||
362 | } | ||
363 | |||
364 | free(dataBuffer); | ||
365 | } | ||
366 | |||
367 | |||
368 | char *quick_read(char *filename) | ||
369 | { | ||
370 | char *result = NULL; | ||
371 | |||
372 | if (stat(filename, &path_stat) == 0) | ||
373 | { | ||
374 | // if (S_ISREG(path_stat.st_mode)) | ||
375 | { | ||
376 | int ifd; | ||
377 | ssize_t size = path_stat.st_size; | ||
378 | |||
379 | if (size <= 0) | ||
380 | size = 1024; | ||
381 | result = (char *) xmalloc (sizeof (char) * size + 1); | ||
382 | if ((ifd = open(filename, O_RDONLY)) < 0) | ||
383 | bb_perror_msg("%s", filename); | ||
384 | else | ||
385 | { | ||
386 | ssize_t total = bb_full_read(ifd, result, size); | ||
387 | // result[path_stat.st_size] = '\0'; | ||
388 | result[total] = '\0'; | ||
389 | if (close (ifd) < 0) | ||
390 | bb_perror_msg("%s", filename); | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
395 | return result; | ||
396 | } | ||
397 | |||
398 | |||
399 | void quick_write(const char *filename, const char *data, ...) | ||
400 | { | ||
401 | char *dataBuffer; | ||
402 | va_list p; | ||
403 | int r; | ||
404 | |||
405 | va_start(p, data); | ||
406 | r = vasprintf(&dataBuffer, data, p); | ||
407 | va_end(p); | ||
408 | if (r >= 0) | ||
409 | { | ||
410 | int ofd; | ||
411 | |||
412 | if ((ofd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) | ||
413 | bb_perror_msg("%s", filename); | ||
414 | else | ||
415 | { | ||
416 | r = bb_full_write(ofd, dataBuffer, r); | ||
417 | if (close (ofd) < 0) | ||
418 | bb_perror_msg("%s", filename); | ||
419 | } | ||
420 | } | ||
421 | if (r < 0) | ||
422 | bb_perror_msg("quick_write"); | ||
423 | |||
424 | free(dataBuffer); | ||
425 | } | ||