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#include "libbb.h"
58
59struct globals {
60 char **names;
61 int cur;
62 char *cmd[2 ];
63} FIX_ALIASING;
64#define G (*(struct globals*)&bb_common_bufsiz1)
65#define names (G.names)
66#define cur (G.cur )
67#define cmd (G.cmd )
68#define INIT_G() do { } while (0)
69
70enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(G)) / sizeof(cmd[0]) - 1 };
71
72enum {
73 OPT_a = (1 << 0),
74 OPT_u = (1 << 1),
75 OPT_r = (1 << 2) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
76 OPT_t = (1 << 3) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
77 OPT_e = (1 << 4) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS,
78 OPT_l = (1 << 5) * ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
79 * ENABLE_FEATURE_RUN_PARTS_FANCY,
80};
81
82
83
84
85static bool invalid_name(const char *c)
86{
87 c = bb_basename(c);
88
89 while (*c && (isalnum(*c) || *c == '_' || *c == '-'))
90 c++;
91
92 return *c;
93}
94
95static int bb_alphasort(const void *p1, const void *p2)
96{
97 int r = strcmp(*(char **) p1, *(char **) p2);
98 return (option_mask32 & OPT_r) ? -r : r;
99}
100
101static int FAST_FUNC act(const char *file, struct stat *statbuf, void *args UNUSED_PARAM, int depth)
102{
103 if (depth == 1)
104 return TRUE;
105
106 if (depth == 2
107 && ( !(statbuf->st_mode & (S_IFREG | S_IFLNK))
108 || invalid_name(file)
109 || (!(option_mask32 & OPT_l) && access(file, X_OK) != 0))
110 ) {
111 return SKIP;
112 }
113
114 names = xrealloc_vector(names, 4, cur);
115 names[cur++] = xstrdup(file);
116
117
118 return TRUE;
119}
120
121#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
122static const char runparts_longopts[] ALIGN1 =
123 "arg\0" Required_argument "a"
124 "umask\0" Required_argument "u"
125
126 "reverse\0" No_argument "\xf0"
127 "test\0" No_argument "\xf1"
128 "exit-on-error\0" No_argument "\xf2"
129#if ENABLE_FEATURE_RUN_PARTS_FANCY
130 "list\0" No_argument "\xf3"
131#endif
132 ;
133#endif
134
135int run_parts_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
136int run_parts_main(int argc UNUSED_PARAM, char **argv)
137{
138 const char *umask_p = "22";
139 llist_t *arg_list = NULL;
140 unsigned n;
141 int ret;
142
143 INIT_G();
144
145#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
146 applet_long_options = runparts_longopts;
147#endif
148
149 opt_complementary = "=1:a::";
150 getopt32(argv, "a:u:", &arg_list, &umask_p);
151
152 umask(xstrtou_range(umask_p, 8, 0, 07777));
153
154 n = 1;
155 while (arg_list && n < NUM_CMD) {
156 cmd[n++] = llist_pop(&arg_list);
157 }
158
159
160
161
162 recursive_action(argv[optind],
163 ACTION_RECURSE|ACTION_FOLLOWLINKS,
164 act,
165 act,
166 NULL,
167 1
168 );
169
170 if (!names)
171 return 0;
172
173 qsort(names, cur, sizeof(char *), bb_alphasort);
174
175 n = 0;
176 while (1) {
177 char *name = *names++;
178 if (!name)
179 break;
180 if (option_mask32 & (OPT_t | OPT_l)) {
181 puts(name);
182 continue;
183 }
184 cmd[0] = name;
185 ret = spawn_and_wait(cmd);
186 if (ret == 0)
187 continue;
188 n = 1;
189 if (ret < 0)
190 bb_perror_msg("can't execute '%s'", name);
191 else
192 bb_error_msg("%s exited with code %d", name, ret & 0xff);
193
194 if (option_mask32 & OPT_e)
195 xfunc_die();
196 }
197
198 return n;
199}
200