aboutsummaryrefslogtreecommitdiff
path: root/debianutils
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-23 18:34:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-23 18:34:49 +0000
commit2a1d024333b56a8de1ebd61405ea8f2577127dd8 (patch)
tree829b73979ce303e0c43a477a291b0265d48706c8 /debianutils
parent06b3cc281108ce585bf33113aa36b29ea0b446cd (diff)
downloadbusybox-w32-2a1d024333b56a8de1ebd61405ea8f2577127dd8.tar.gz
busybox-w32-2a1d024333b56a8de1ebd61405ea8f2577127dd8.tar.bz2
busybox-w32-2a1d024333b56a8de1ebd61405ea8f2577127dd8.zip
run_parts: make it sort executables by name (required by API)
Diffstat (limited to 'debianutils')
-rw-r--r--debianutils/run_parts.c174
1 files changed, 101 insertions, 73 deletions
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index 0104eb111..56f70c6ee 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -34,27 +34,32 @@
34 34
35#include "libbb.h" 35#include "libbb.h"
36 36
37#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
38static const char runparts_longopts[] ALIGN1 =
39 "arg\0" Required_argument "a"
40 "umask\0" Required_argument "u"
41 "test\0" No_argument "t"
42#if ENABLE_FEATURE_RUN_PARTS_FANCY
43 "list\0" No_argument "l"
44//TODO: "reverse\0" No_argument "r"
45//TODO: "verbose\0" No_argument "v"
46#endif
47 ;
48#endif
49
50struct globals { 37struct globals {
51 smalluint mode; 38 char **names;
52 char *cmd[10]; /* merely arbitrary arg count */ 39 int cur;
40 char *cmd[1];
53}; 41};
54#define G (*(struct globals*)&bb_common_bufsiz1) 42#define G (*(struct globals*)&bb_common_bufsiz1)
43#define names (G.names)
44#define cur (G.cur )
45#define cmd (G.cmd )
46
47enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(struct globals)) / sizeof(cmd[0]) };
48
49enum {
50 RUN_PARTS_OPT_a = (1 << 0),
51 RUN_PARTS_OPT_u = (1 << 1),
52 RUN_PARTS_OPT_t = (1 << 2),
53 RUN_PARTS_OPT_l = (1 << 3) * ENABLE_FEATURE_RUN_PARTS_FANCY,
54};
55
56#if ENABLE_FEATURE_RUN_PARTS_FANCY
57#define list_mode (option_mask32 & RUN_PARTS_OPT_l)
58#else
59#define list_mode 0
60#endif
55 61
56/* valid_name */ 62/* Is this a valid filename (upper/lower alpha, digits,
57/* True or false? Is this a valid filename (upper/lower alpha, digits,
58 * underscores, and hyphens only?) 63 * underscores, and hyphens only?)
59 */ 64 */
60static bool invalid_name(const char *c) 65static bool invalid_name(const char *c)
@@ -67,80 +72,103 @@ static bool invalid_name(const char *c)
67 return *c; /* TRUE (!0) if terminating NUL is not reached */ 72 return *c; /* TRUE (!0) if terminating NUL is not reached */
68} 73}
69 74
70#define RUN_PARTS_OPT_a (1<<0) 75static int bb_alphasort(const void *p1, const void *p2)
71#define RUN_PARTS_OPT_u (1<<1) 76{
72#define RUN_PARTS_OPT_t (1<<2) 77 return strcmp(*(char **) p1, *(char **) p2);
73#if ENABLE_FEATURE_RUN_PARTS_FANCY 78}
74#define RUN_PARTS_OPT_l (1<<3)
75#endif
76
77#define test_mode (G.mode & RUN_PARTS_OPT_t)
78#if ENABLE_FEATURE_RUN_PARTS_FANCY
79#define list_mode (G.mode & RUN_PARTS_OPT_l)
80#else
81#define list_mode (0)
82#endif
83 79
84static int act(const char *file, struct stat *statbuf, void *args, int depth) 80static int act(const char *file, struct stat *statbuf, void *args, int depth)
85{ 81{
86 int ret;
87
88 if (depth == 1) 82 if (depth == 1)
89 return TRUE; 83 return TRUE;
90 84
91 if (depth == 2 && 85 if (depth == 2
92 ((!list_mode && access(file, X_OK)) || 86 && ( !(statbuf->st_mode & (S_IFREG | S_IFLNK))
93 invalid_name(file) || 87 || invalid_name(file)
94 !(statbuf->st_mode & (S_IFREG | S_IFLNK))) ) 88 || (!list_mode && access(file, X_OK) != 0))
89 ) {
95 return SKIP; 90 return SKIP;
96
97 if (test_mode || list_mode) {
98 puts(file);
99 return TRUE;
100 } 91 }
101 G.cmd[0] = (char*)file; 92
102 ret = wait4pid(spawn(G.cmd)); 93 names = xrealloc(names, (cur + 2) * sizeof(names[0]));
103 if (ret < 0) { 94 names[cur++] = xstrdup(file);
104 bb_perror_msg("failed to exec %s", file); 95 names[cur] = NULL;
105 } else if (ret > 0) { 96
106 bb_error_msg("%s exited with return code %d", file, ret); 97 return TRUE;
107 }
108 return !ret;
109} 98}
110 99
100#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
101static const char runparts_longopts[] ALIGN1 =
102 "arg\0" Required_argument "a"
103 "umask\0" Required_argument "u"
104 "test\0" No_argument "t"
105#if ENABLE_FEATURE_RUN_PARTS_FANCY
106 "list\0" No_argument "l"
107//TODO: "reverse\0" No_argument "r"
108//TODO: "verbose\0" No_argument "v"
109#endif
110 ;
111#endif
112
111int run_parts_main(int argc, char **argv); 113int run_parts_main(int argc, char **argv);
112int run_parts_main(int argc, char **argv) 114int run_parts_main(int argc, char **argv)
113{ 115{
114 char *umask_p; 116 const char *umask_p = "22";
115 llist_t *arg_list = NULL; 117 llist_t *arg_list = NULL;
116 unsigned tmp; 118 unsigned n;
119 int ret;
117 120
118 umask(022);
119 /* We require exactly one argument: the directory name */
120 opt_complementary = "=1:a::";
121#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS 121#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
122 applet_long_options = runparts_longopts; 122 applet_long_options = runparts_longopts;
123#endif 123#endif
124 tmp = getopt32(argv, "a:u:t"USE_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p); 124 /* We require exactly one argument: the directory name */
125 G.mode = tmp &~ (RUN_PARTS_OPT_a|RUN_PARTS_OPT_u); 125 opt_complementary = "=1:a::";
126 if (tmp & RUN_PARTS_OPT_u) { 126 getopt32(argv, "a:u:t"USE_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p);
127 /* Check and set the umask of the program executed. 127
128 * As stated in the original run-parts, the octal conversion in 128 umask(xstrtou_range(umask_p, 8, 0, 07777));
129 * libc is not foolproof; it will take the 8 and 9 digits under 129
130 * some circumstances. We'll just have to live with it. 130 n = 1;
131 */ 131 while (arg_list && n < NUM_CMD) {
132 umask(xstrtoul_range(umask_p, 8, 0, 07777)); 132 cmd[n] = arg_list->data;
133 arg_list = arg_list->link;
134 n++;
133 } 135 }
134 for (tmp = 1; arg_list; arg_list = arg_list->link, tmp++) 136 /* cmd[n] = NULL; - is already zeroed out */
135 G.cmd[tmp] = arg_list->data; 137
136 /* G.cmd[tmp] = NULL; - G is already zeroed out */ 138 /* run-parts has to sort executables by name before running them */
137 if (!recursive_action(argv[argc - 1], 139
140 recursive_action(argv[optind],
138 ACTION_RECURSE|ACTION_FOLLOWLINKS, 141 ACTION_RECURSE|ACTION_FOLLOWLINKS,
139 act, /* file action */ 142 act, /* file action */
140 act, /* dir action */ 143 act, /* dir action */
141 NULL, /* user data */ 144 NULL, /* user data */
142 1 /* depth */ 145 1 /* depth */
143 )) 146 );
144 return EXIT_FAILURE; 147
145 return EXIT_SUCCESS; 148 if (!names)
149 return 0;
150
151 qsort(names, cur, sizeof(char *), bb_alphasort);
152
153 n = 0;
154 while (1) {
155 char *name = *names++;
156 if (!name)
157 break;
158 if (option_mask32 & (RUN_PARTS_OPT_t | RUN_PARTS_OPT_l)) {
159 puts(name);
160 continue;
161 }
162 cmd[0] = name;
163 ret = wait4pid(spawn(cmd));
164 if (ret == 0)
165 continue;
166 n = 1;
167 if (ret < 0)
168 bb_perror_msg("failed to exec %s", name);
169 else /* ret > 0 */
170 bb_error_msg("%s exited with return code %d", name, ret);
171 }
172
173 return n;
146} 174}