diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-23 18:34:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-09-23 18:34:49 +0000 |
commit | 2a1d024333b56a8de1ebd61405ea8f2577127dd8 (patch) | |
tree | 829b73979ce303e0c43a477a291b0265d48706c8 /debianutils | |
parent | 06b3cc281108ce585bf33113aa36b29ea0b446cd (diff) | |
download | busybox-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.c | 174 |
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 | ||
38 | static 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 | |||
50 | struct globals { | 37 | struct 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 | |||
47 | enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(struct globals)) / sizeof(cmd[0]) }; | ||
48 | |||
49 | enum { | ||
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 | */ |
60 | static bool invalid_name(const char *c) | 65 | static 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) | 75 | static 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 | ||
84 | static int act(const char *file, struct stat *statbuf, void *args, int depth) | 80 | static 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 | ||
101 | static 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 | |||
111 | int run_parts_main(int argc, char **argv); | 113 | int run_parts_main(int argc, char **argv); |
112 | int run_parts_main(int argc, char **argv) | 114 | int 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 | } |