aboutsummaryrefslogtreecommitdiff
path: root/findutils/xargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'findutils/xargs.c')
-rw-r--r--findutils/xargs.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 35a06f723..d014669bd 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -74,6 +74,9 @@
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#endif
77#include "libbb.h" 80#include "libbb.h"
78#include "common_bufsiz.h" 81#include "common_bufsiz.h"
79 82
@@ -112,6 +115,9 @@ struct globals {
112#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 115#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
113 int running_procs; 116 int running_procs;
114 int max_procs; 117 int max_procs;
118#if ENABLE_PLATFORM_MINGW32
119 HANDLE *procs;
120#endif
115#endif 121#endif
116 smalluint xargs_exitcode; 122 smalluint xargs_exitcode;
117} FIX_ALIASING; 123} FIX_ALIASING;
@@ -122,12 +128,61 @@ struct globals {
122 G.idx = 0; \ 128 G.idx = 0; \
123 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \ 129 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \
124 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \ 130 IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \
131 IF_FEATURE_XARGS_SUPPORT_PARALLEL(IF_PLATFORM_MINGW32(G.procs = NULL;)) \
125 G.xargs_exitcode = 0; \ 132 G.xargs_exitcode = 0; \
126 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \ 133 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \
127 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \ 134 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \
128} while (0) 135} while (0)
129 136
130 137
138#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32
139static int wait_for_slot(int *idx)
140{
141 int i;
142
143 /* if less than max_procs running, set status to 0, return next free slot */
144 if (G.running_procs < G.max_procs) {
145 *idx = G.running_procs++;
146 return 0;
147 }
148
149check_exit_codes:
150 for (i = G.running_procs - 1; i >= 0; i--) {
151 DWORD status = 0;
152 if (!GetExitCodeProcess(G.procs[i], &status) ||
153 status != STILL_ACTIVE) {
154 CloseHandle(G.procs[i]);
155 if (i + 1 < G.running_procs)
156 G.procs[i] = G.procs[G.running_procs - 1];
157 *idx = G.running_procs - 1;
158 if (!G.max_procs)
159 G.running_procs--;
160 return status;
161 }
162 }
163
164 if (G.running_procs < MAXIMUM_WAIT_OBJECTS)
165 WaitForMultipleObjects((DWORD)G.running_procs, G.procs, FALSE,
166 INFINITE);
167 else {
168 /* Fall back to polling */
169 for (;;) {
170 DWORD nr = i + MAXIMUM_WAIT_OBJECTS > G.running_procs ?
171 MAXIMUM_WAIT_OBJECTS : (DWORD)(G.running_procs - i);
172 DWORD ret = WaitForMultipleObjects(nr, G.procs + i, FALSE, 100);
173
174 if (ret != WAIT_TIMEOUT)
175 break;
176 i += MAXIMUM_WAIT_OBJECTS;
177 if (i > G.running_procs)
178 i = 0;
179 }
180 }
181
182 goto check_exit_codes;
183}
184#endif /* SUPPORT_PARALLEL && PLATFORM_MINGW32 */
185
131/* 186/*
132 * Returns 0 if xargs should continue (but may set G.xargs_exitcode to 123). 187 * Returns 0 if xargs should continue (but may set G.xargs_exitcode to 123).
133 * Else sets G.xargs_exitcode to error code and returns nonzero. 188 * Else sets G.xargs_exitcode to error code and returns nonzero.
@@ -144,6 +199,23 @@ static int xargs_exec(void)
144 if (G.max_procs == 1) { 199 if (G.max_procs == 1) {
145 status = spawn_and_wait(G.args); 200 status = spawn_and_wait(G.args);
146 } else { 201 } else {
202#if ENABLE_PLATFORM_MINGW32
203 int idx;
204 status = !G.running_procs && !G.max_procs ? 0 : wait_for_slot(&idx);
205 if (G.max_procs) {
206 HANDLE p = (HANDLE)mingw_spawn_proc((const char **)G.args);
207 if (p < 0)
208 status = -1;
209 else
210 G.procs[idx] = p;
211 } else {
212 while (G.running_procs) {
213 int status2 = wait_for_slot(&idx);
214 if (status2 && !status)
215 status = status2;
216 }
217 }
218#else
147 pid_t pid; 219 pid_t pid;
148 int wstat; 220 int wstat;
149 again: 221 again:
@@ -184,6 +256,7 @@ static int xargs_exec(void)
184 /* final waitpid() loop: must be ECHILD "no more children" */ 256 /* final waitpid() loop: must be ECHILD "no more children" */
185 status = 0; 257 status = 0;
186 } 258 }
259#endif
187 } 260 }
188#endif 261#endif
189 /* Manpage: 262 /* Manpage:
@@ -496,6 +569,7 @@ static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg
496 */ 569 */
497static int xargs_ask_confirmation(void) 570static int xargs_ask_confirmation(void)
498{ 571{
572#if !ENABLE_PLATFORM_MINGW32
499 FILE *tty_stream; 573 FILE *tty_stream;
500 int r; 574 int r;
501 575
@@ -505,6 +579,18 @@ static int xargs_ask_confirmation(void)
505 r = bb_ask_y_confirmation_FILE(tty_stream); 579 r = bb_ask_y_confirmation_FILE(tty_stream);
506 580
507 fclose(tty_stream); 581 fclose(tty_stream);
582#else
583 int r, c, savec;
584
585 fputs(" ?...", stderr);
586 fflush_all();
587 c = savec = getche();
588 while (c != EOF && c != '\r')
589 c = getche();
590 fputs("\n", stderr);
591 fflush_all();
592 r = (savec == 'y' || savec == 'Y');
593#endif
508 594
509 return r; 595 return r;
510} 596}
@@ -608,7 +694,12 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
608 694
609#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 695#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
610 if (G.max_procs <= 0) /* -P0 means "run lots of them" */ 696 if (G.max_procs <= 0) /* -P0 means "run lots of them" */
697#if !ENABLE_PLATFORM_MINGW32
611 G.max_procs = 100; /* let's not go crazy high */ 698 G.max_procs = 100; /* let's not go crazy high */
699#else
700 G.max_procs = MAXIMUM_WAIT_OBJECTS;
701 G.procs = xmalloc(sizeof(G.procs[0]) * G.max_procs);
702#endif
612#endif 703#endif
613 704
614#if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE 705#if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE
@@ -730,7 +821,11 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
730 fmt = " %s"; 821 fmt = " %s";
731 } 822 }
732 if (!(opt & OPT_INTERACTIVE)) 823 if (!(opt & OPT_INTERACTIVE))
824#if !ENABLE_PLATFORM_MINGW32
733 bb_putchar_stderr('\n'); 825 bb_putchar_stderr('\n');
826#else
827 fprintf(stderr, "\n");
828#endif
734 } 829 }
735 830
736 if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) { 831 if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) {