diff options
Diffstat (limited to 'findutils/xargs.c')
-rw-r--r-- | findutils/xargs.c | 167 |
1 files changed, 164 insertions, 3 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c index 890c37534..37064be9d 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -74,6 +74,11 @@ | |||
74 | 74 | ||
75 | //kbuild:lib-$(CONFIG_XARGS) += xargs.o | 75 | //kbuild:lib-$(CONFIG_XARGS) += xargs.o |
76 | 76 | ||
77 | #if ENABLE_PLATFORM_MINGW32 | ||
78 | #include <conio.h> | ||
79 | #include "busybox.h" | ||
80 | #include "NUM_APPLETS.h" | ||
81 | #endif | ||
77 | #include "libbb.h" | 82 | #include "libbb.h" |
78 | #include "common_bufsiz.h" | 83 | #include "common_bufsiz.h" |
79 | 84 | ||
@@ -111,11 +116,19 @@ struct globals { | |||
111 | #endif | 116 | #endif |
112 | const char *eof_str; | 117 | const char *eof_str; |
113 | int idx; | 118 | int idx; |
119 | #if !ENABLE_PLATFORM_MINGW32 | ||
114 | int fd_tty; | 120 | int fd_tty; |
115 | int fd_stdin; | 121 | int fd_stdin; |
122 | #endif | ||
116 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | 123 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL |
117 | int running_procs; | 124 | int running_procs; |
118 | int max_procs; | 125 | int max_procs; |
126 | # if ENABLE_PLATFORM_MINGW32 | ||
127 | HANDLE *procs; | ||
128 | # endif | ||
129 | #endif | ||
130 | #if ENABLE_PLATFORM_MINGW32 | ||
131 | pid_t pid; | ||
119 | #endif | 132 | #endif |
120 | smalluint xargs_exitcode; | 133 | smalluint xargs_exitcode; |
121 | #if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES | 134 | #if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES |
@@ -137,6 +150,7 @@ struct globals { | |||
137 | G.idx = 0; \ | 150 | G.idx = 0; \ |
138 | IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \ | 151 | IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \ |
139 | IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \ | 152 | IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \ |
153 | IF_FEATURE_XARGS_SUPPORT_PARALLEL(IF_PLATFORM_MINGW32(G.procs = NULL;)) \ | ||
140 | G.xargs_exitcode = 0; \ | 154 | G.xargs_exitcode = 0; \ |
141 | IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__state = NORM;) \ | 155 | IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__state = NORM;) \ |
142 | IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \ | 156 | IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \ |
@@ -150,7 +164,7 @@ enum { | |||
150 | OPTBIT_UPTO_SIZE, | 164 | OPTBIT_UPTO_SIZE, |
151 | OPTBIT_EOF_STRING, | 165 | OPTBIT_EOF_STRING, |
152 | OPTBIT_EOF_STRING1, | 166 | OPTBIT_EOF_STRING1, |
153 | OPTBIT_STDIN_TTY, | 167 | IF_NOT_PLATFORM_MINGW32( OPTBIT_STDIN_TTY ,) |
154 | IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) | 168 | IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) |
155 | IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) | 169 | IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) |
156 | IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) | 170 | IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) |
@@ -163,14 +177,15 @@ enum { | |||
163 | OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE , | 177 | OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE , |
164 | OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[<param>] */ | 178 | OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[<param>] */ |
165 | OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E<param> */ | 179 | OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E<param> */ |
166 | OPT_STDIN_TTY = 1 << OPTBIT_STDIN_TTY, | 180 | OPT_STDIN_TTY = IF_NOT_PLATFORM_MINGW32( (1 << OPTBIT_STDIN_TTY )) + 0, |
167 | OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0, | 181 | OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0, |
168 | OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0, | 182 | OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0, |
169 | OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0, | 183 | OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0, |
170 | OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0, | 184 | OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0, |
171 | OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0, | 185 | OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0, |
172 | }; | 186 | }; |
173 | #define OPTION_STR "+trn:s:e::E:o" \ | 187 | #define OPTION_STR "+trn:s:e::E:" \ |
188 | IF_NOT_PLATFORM_MINGW32( "o") \ | ||
174 | IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ | 189 | IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ |
175 | IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ | 190 | IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ |
176 | IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \ | 191 | IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \ |
@@ -179,6 +194,83 @@ enum { | |||
179 | IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") | 194 | IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") |
180 | 195 | ||
181 | 196 | ||
197 | #if ENABLE_PLATFORM_MINGW32 | ||
198 | static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) | ||
199 | { | ||
200 | if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) { | ||
201 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
202 | if (G.max_procs == 1) | ||
203 | # endif | ||
204 | { | ||
205 | if (G.pid > 0) | ||
206 | kill(-G.pid, SIGTERM); | ||
207 | } | ||
208 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
209 | else { | ||
210 | int i; | ||
211 | |||
212 | for (i = 0; i < G.running_procs; ++i) { | ||
213 | pid_t pid = GetProcessId(G.procs[i]); | ||
214 | if (pid > 0) | ||
215 | kill(-pid, SIGTERM); | ||
216 | } | ||
217 | } | ||
218 | # endif | ||
219 | exit(SIGINT << 24); | ||
220 | return TRUE; | ||
221 | } | ||
222 | return FALSE; | ||
223 | } | ||
224 | #endif | ||
225 | |||
226 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32 | ||
227 | static int wait_for_slot(int *idx) | ||
228 | { | ||
229 | int i; | ||
230 | |||
231 | /* if less than max_procs running, set status to 0, return next free slot */ | ||
232 | if (G.running_procs < G.max_procs) { | ||
233 | *idx = G.running_procs++; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | check_exit_codes: | ||
238 | for (i = G.running_procs - 1; i >= 0; i--) { | ||
239 | DWORD status = 0; | ||
240 | if (!GetExitCodeProcess(G.procs[i], &status) || | ||
241 | status != STILL_ACTIVE) { | ||
242 | CloseHandle(G.procs[i]); | ||
243 | if (i + 1 < G.running_procs) | ||
244 | G.procs[i] = G.procs[G.running_procs - 1]; | ||
245 | *idx = G.running_procs - 1; | ||
246 | if (!G.max_procs) | ||
247 | G.running_procs--; | ||
248 | return status; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | if (G.running_procs < MAXIMUM_WAIT_OBJECTS) | ||
253 | WaitForMultipleObjects((DWORD)G.running_procs, G.procs, FALSE, | ||
254 | INFINITE); | ||
255 | else { | ||
256 | /* Fall back to polling */ | ||
257 | for (;;) { | ||
258 | DWORD nr = i + MAXIMUM_WAIT_OBJECTS > G.running_procs ? | ||
259 | MAXIMUM_WAIT_OBJECTS : (DWORD)(G.running_procs - i); | ||
260 | DWORD ret = WaitForMultipleObjects(nr, G.procs + i, FALSE, 100); | ||
261 | |||
262 | if (ret != WAIT_TIMEOUT) | ||
263 | break; | ||
264 | i += MAXIMUM_WAIT_OBJECTS; | ||
265 | if (i > G.running_procs) | ||
266 | i = 0; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | goto check_exit_codes; | ||
271 | } | ||
272 | #endif /* SUPPORT_PARALLEL && PLATFORM_MINGW32 */ | ||
273 | |||
182 | /* | 274 | /* |
183 | * Returns 0 if xargs should continue (but may set G.xargs_exitcode to 123). | 275 | * Returns 0 if xargs should continue (but may set G.xargs_exitcode to 123). |
184 | * Else sets G.xargs_exitcode to error code and returns nonzero. | 276 | * Else sets G.xargs_exitcode to error code and returns nonzero. |
@@ -189,6 +281,7 @@ static int xargs_exec(void) | |||
189 | { | 281 | { |
190 | int status; | 282 | int status; |
191 | 283 | ||
284 | #if !ENABLE_PLATFORM_MINGW32 | ||
192 | if (option_mask32 & OPT_STDIN_TTY) | 285 | if (option_mask32 & OPT_STDIN_TTY) |
193 | xdup2(G.fd_tty, STDIN_FILENO); | 286 | xdup2(G.fd_tty, STDIN_FILENO); |
194 | 287 | ||
@@ -240,6 +333,43 @@ static int xargs_exec(void) | |||
240 | } | 333 | } |
241 | } | 334 | } |
242 | #endif | 335 | #endif |
336 | #endif | ||
337 | |||
338 | #if ENABLE_PLATFORM_MINGW32 | ||
339 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
340 | if (G.max_procs == 1) { | ||
341 | # endif | ||
342 | # if ENABLE_FEATURE_PREFER_APPLETS && (NUM_APPLETS > 1) | ||
343 | int applet = find_applet_by_name(G.args[0]); | ||
344 | if (applet >= 0 && APPLET_IS_NOFORK(applet)) { | ||
345 | status = run_nofork_applet(applet, G.args); | ||
346 | } else | ||
347 | # endif | ||
348 | { | ||
349 | G.pid = spawn(G.args); | ||
350 | status = G.pid < 0 ? -1 : wait4pid(G.pid); | ||
351 | } | ||
352 | # if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | ||
353 | } | ||
354 | else { | ||
355 | int idx; | ||
356 | status = !G.running_procs && !G.max_procs ? 0 : wait_for_slot(&idx); | ||
357 | if (G.max_procs) { | ||
358 | HANDLE p = (HANDLE)mingw_spawn_proc((const char **)G.args); | ||
359 | if (p < 0) | ||
360 | status = -1; | ||
361 | else | ||
362 | G.procs[idx] = p; | ||
363 | } else { | ||
364 | while (G.running_procs) { | ||
365 | int status2 = wait_for_slot(&idx); | ||
366 | if (status2 && !status) | ||
367 | status = status2; | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | # endif | ||
372 | #endif | ||
243 | /* Manpage: | 373 | /* Manpage: |
244 | * """xargs exits with the following status: | 374 | * """xargs exits with the following status: |
245 | * 0 if it succeeds | 375 | * 0 if it succeeds |
@@ -278,8 +408,10 @@ static int xargs_exec(void) | |||
278 | ret: | 408 | ret: |
279 | if (status != 0) | 409 | if (status != 0) |
280 | G.xargs_exitcode = status; | 410 | G.xargs_exitcode = status; |
411 | #if !ENABLE_PLATFORM_MINGW32 | ||
281 | if (option_mask32 & OPT_STDIN_TTY) | 412 | if (option_mask32 & OPT_STDIN_TTY) |
282 | xdup2(G.fd_stdin, STDIN_FILENO); | 413 | xdup2(G.fd_stdin, STDIN_FILENO); |
414 | #endif | ||
283 | return status; | 415 | return status; |
284 | } | 416 | } |
285 | 417 | ||
@@ -559,6 +691,7 @@ static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg | |||
559 | */ | 691 | */ |
560 | static int xargs_ask_confirmation(void) | 692 | static int xargs_ask_confirmation(void) |
561 | { | 693 | { |
694 | #if !ENABLE_PLATFORM_MINGW32 | ||
562 | FILE *tty_stream; | 695 | FILE *tty_stream; |
563 | int r; | 696 | int r; |
564 | 697 | ||
@@ -568,6 +701,18 @@ static int xargs_ask_confirmation(void) | |||
568 | r = bb_ask_y_confirmation_FILE(tty_stream); | 701 | r = bb_ask_y_confirmation_FILE(tty_stream); |
569 | 702 | ||
570 | fclose(tty_stream); | 703 | fclose(tty_stream); |
704 | #else | ||
705 | int r, c, savec; | ||
706 | |||
707 | fputs(" ?...", stderr); | ||
708 | fflush_all(); | ||
709 | c = savec = getche(); | ||
710 | while (c != EOF && c != '\r') | ||
711 | c = getche(); | ||
712 | fputs("\n", stderr); | ||
713 | fflush_all(); | ||
714 | r = (savec == 'y' || savec == 'Y'); | ||
715 | #endif | ||
571 | 716 | ||
572 | return r; | 717 | return r; |
573 | } | 718 | } |
@@ -585,7 +730,9 @@ static int xargs_ask_confirmation(void) | |||
585 | //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( | 730 | //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( |
586 | //usage: "\n -a FILE Read from FILE instead of stdin" | 731 | //usage: "\n -a FILE Read from FILE instead of stdin" |
587 | //usage: ) | 732 | //usage: ) |
733 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
588 | //usage: "\n -o Reopen stdin as /dev/tty" | 734 | //usage: "\n -o Reopen stdin as /dev/tty" |
735 | //usage: ) | ||
589 | //usage: "\n -r Don't run command if input is empty" | 736 | //usage: "\n -r Don't run command if input is empty" |
590 | //usage: "\n -t Print the command on stderr before execution" | 737 | //usage: "\n -t Print the command on stderr before execution" |
591 | //usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION( | 738 | //usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION( |
@@ -628,6 +775,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv) | |||
628 | 775 | ||
629 | INIT_G(); | 776 | INIT_G(); |
630 | 777 | ||
778 | #if ENABLE_PLATFORM_MINGW32 | ||
779 | SetConsoleCtrlHandler(ctrl_handler, TRUE); | ||
780 | #endif | ||
631 | opt = getopt32long(argv, OPTION_STR, | 781 | opt = getopt32long(argv, OPTION_STR, |
632 | "no-run-if-empty\0" No_argument "r", | 782 | "no-run-if-empty\0" No_argument "r", |
633 | &max_args, &max_chars, &G.eof_str, &G.eof_str | 783 | &max_args, &max_chars, &G.eof_str, &G.eof_str |
@@ -638,7 +788,12 @@ int xargs_main(int argc UNUSED_PARAM, char **argv) | |||
638 | 788 | ||
639 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL | 789 | #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL |
640 | if (G.max_procs <= 0) /* -P0 means "run lots of them" */ | 790 | if (G.max_procs <= 0) /* -P0 means "run lots of them" */ |
791 | #if !ENABLE_PLATFORM_MINGW32 | ||
641 | G.max_procs = 100; /* let's not go crazy high */ | 792 | G.max_procs = 100; /* let's not go crazy high */ |
793 | #else | ||
794 | G.max_procs = MAXIMUM_WAIT_OBJECTS; | ||
795 | G.procs = xmalloc(sizeof(G.procs[0]) * G.max_procs); | ||
796 | #endif | ||
642 | #endif | 797 | #endif |
643 | 798 | ||
644 | #if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE | 799 | #if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE |
@@ -736,12 +891,14 @@ int xargs_main(int argc UNUSED_PARAM, char **argv) | |||
736 | store_param(argv[i]); | 891 | store_param(argv[i]); |
737 | } | 892 | } |
738 | 893 | ||
894 | #if !ENABLE_PLATFORM_MINGW32 | ||
739 | if (opt & OPT_STDIN_TTY) { | 895 | if (opt & OPT_STDIN_TTY) { |
740 | G.fd_tty = xopen(CURRENT_TTY, O_RDONLY); | 896 | G.fd_tty = xopen(CURRENT_TTY, O_RDONLY); |
741 | close_on_exec_on(G.fd_tty); | 897 | close_on_exec_on(G.fd_tty); |
742 | G.fd_stdin = dup(STDIN_FILENO); | 898 | G.fd_stdin = dup(STDIN_FILENO); |
743 | close_on_exec_on(G.fd_stdin); | 899 | close_on_exec_on(G.fd_stdin); |
744 | } | 900 | } |
901 | #endif | ||
745 | 902 | ||
746 | initial_idx = G.idx; | 903 | initial_idx = G.idx; |
747 | while (1) { | 904 | while (1) { |
@@ -767,7 +924,11 @@ int xargs_main(int argc UNUSED_PARAM, char **argv) | |||
767 | fmt = " %s"; | 924 | fmt = " %s"; |
768 | } | 925 | } |
769 | if (!(opt & OPT_INTERACTIVE)) | 926 | if (!(opt & OPT_INTERACTIVE)) |
927 | #if !ENABLE_PLATFORM_MINGW32 | ||
770 | bb_putchar_stderr('\n'); | 928 | bb_putchar_stderr('\n'); |
929 | #else | ||
930 | fprintf(stderr, "\n"); | ||
931 | #endif | ||
771 | } | 932 | } |
772 | 933 | ||
773 | if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) { | 934 | if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) { |