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