summaryrefslogtreecommitdiffstats
path: root/urunlevel/runlevel/lib_init_d.c
diff options
context:
space:
mode:
Diffstat (limited to 'urunlevel/runlevel/lib_init_d.c')
-rw-r--r--urunlevel/runlevel/lib_init_d.c425
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
35static char *shell = 0;
36struct stat path_stat;
37
38
39char *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
63char *big_chomp(char *s)
64{
65 char *lc = index(s, '\n');
66
67 if(lc)
68 *lc = '\0';
69 return s;
70}
71
72
73char *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.
259llist_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
284llist_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
303void 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
323void 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
348void 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
368char *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
399void 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}