summaryrefslogtreecommitdiff
path: root/debianutils/run_parts.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-26 20:13:39 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-26 20:13:39 +0000
commite5667c1cfe339b2f84abaabb90259ec29b91cf89 (patch)
tree385d96cede38de88bcc55cf2e02c36deb86f25a5 /debianutils/run_parts.c
parentec0c920a78813d1c047924e024017189dedeec93 (diff)
downloadbusybox-w32-e5667c1cfe339b2f84abaabb90259ec29b91cf89.tar.gz
busybox-w32-e5667c1cfe339b2f84abaabb90259ec29b91cf89.tar.bz2
busybox-w32-e5667c1cfe339b2f84abaabb90259ec29b91cf89.zip
Closing bug 730. libbb run_parts is using scandir (a GNUism),
and it is used only by run_parts applet, so move it there. Also saved ~30 bytes (prolly gcc autoinlining...).
Diffstat (limited to 'debianutils/run_parts.c')
-rw-r--r--debianutils/run_parts.c107
1 files changed, 99 insertions, 8 deletions
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index f2d90b64d..448fe80c1 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -37,17 +37,108 @@
37 37
38#include "busybox.h" 38#include "busybox.h"
39#include <getopt.h> 39#include <getopt.h>
40#include <stdlib.h>
41
42 40
43static const struct option runparts_long_options[] = { 41static const struct option runparts_long_options[] = {
44 { "test", 0, NULL, 't' }, 42 { "test", 0, NULL, 't' },
45 { "umask", 1, NULL, 'u' }, 43 { "umask", 1, NULL, 'u' },
46 { "arg", 1, NULL, 'a' }, 44 { "arg", 1, NULL, 'a' },
47 { 0, 0, 0, 0 } 45 { 0, 0, 0, 0 }
48}; 46};
49 47
50extern char **environ; 48/* valid_name */
49/* True or false? Is this a valid filename (upper/lower alpha, digits,
50 * underscores, and hyphens only?)
51 */
52static int valid_name(const struct dirent *d)
53{
54 const char *c = d->d_name;
55
56 while (*c) {
57 if (!isalnum(*c) && (*c != '_') && (*c != '-')) {
58 return 0;
59 }
60 ++c;
61 }
62 return 1;
63}
64
65/* test mode = 1 is the same as official run_parts
66 * test_mode = 2 means to fail silently on missing directories
67 */
68static int run_parts(char **args, const unsigned char test_mode)
69{
70 struct dirent **namelist = 0;
71 struct stat st;
72 char *filename;
73 char *arg0 = args[0];
74 int entries;
75 int i;
76 int exitstatus = 0;
77
78#if __GNUC__
79 /* Avoid longjmp clobbering */
80 (void) &i;
81 (void) &exitstatus;
82#endif
83 /* scandir() isn't POSIX, but it makes things easy. */
84 entries = scandir(arg0, &namelist, valid_name, alphasort);
85
86 if (entries == -1) {
87 if (test_mode & 2) {
88 return(2);
89 }
90 bb_perror_msg_and_die("cannot open '%s'", arg0);
91 }
92
93 for (i = 0; i < entries; i++) {
94 filename = concat_path_file(arg0, namelist[i]->d_name);
95
96 xstat(filename, &st);
97 if (S_ISREG(st.st_mode) && !access(filename, X_OK)) {
98 if (test_mode) {
99 puts(filename);
100 } else {
101 /* exec_errno is common vfork variable */
102 volatile int exec_errno = 0;
103 int result;
104 int pid;
105
106 if ((pid = vfork()) < 0) {
107 bb_perror_msg_and_die("failed to fork");
108 } else if (!pid) {
109 args[0] = filename;
110 execve(filename, args, environ);
111 exec_errno = errno;
112 _exit(1);
113 }
114
115 waitpid(pid, &result, 0);
116 if (exec_errno) {
117 errno = exec_errno;
118 bb_perror_msg("failed to exec %s", filename);
119 exitstatus = 1;
120 }
121 if (WIFEXITED(result) && WEXITSTATUS(result)) {
122 bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
123 exitstatus = 1;
124 } else if (WIFSIGNALED(result)) {
125 bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
126 exitstatus = 1;
127 }
128 }
129 } else if (!S_ISDIR(st.st_mode)) {
130 bb_error_msg("component %s is not an executable plain file", filename);
131 exitstatus = 1;
132 }
133
134 free(namelist[i]);
135 free(filename);
136 }
137 free(namelist);
138
139 return exitstatus;
140}
141
51 142
52/* run_parts_main */ 143/* run_parts_main */
53/* Process options */ 144/* Process options */
@@ -96,5 +187,5 @@ int run_parts_main(int argc, char **argv)
96 args[0] = argv[optind]; 187 args[0] = argv[optind];
97 args[argcount] = 0; 188 args[argcount] = 0;
98 189
99 return(run_parts(args, test_mode, environ)); 190 return run_parts(args, test_mode);
100} 191}