diff options
Diffstat (limited to 'findutils/xargs.c')
-rw-r--r-- | findutils/xargs.c | 95 |
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 | ||
139 | static 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 | |||
149 | check_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 | */ |
497 | static int xargs_ask_confirmation(void) | 570 | static 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()) { |