aboutsummaryrefslogtreecommitdiff
path: root/findutils/xargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'findutils/xargs.c')
-rw-r--r--findutils/xargs.c268
1 files changed, 263 insertions, 5 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 890c37534..f0abf1a23 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
198static 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
227static 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
237check_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,45 @@ static int xargs_exec(void)
240 } 333 }
241 } 334 }
242#endif 335#endif
336#endif
337
338#if ENABLE_PLATFORM_MINGW32
339 /* Any change to the logic for NOFORK applets must be duplicated
340 * in xargs_main() below. */
341# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
342 if (G.max_procs == 1) {
343# endif
344# if ENABLE_FEATURE_PREFER_APPLETS && (NUM_APPLETS > 1)
345 int applet = find_applet_by_name(G.args[0]);
346 if (applet >= 0 && APPLET_IS_NOFORK(applet)) {
347 status = run_nofork_applet(applet, G.args);
348 } else
349# endif
350 {
351 G.pid = spawn(G.args);
352 status = G.pid < 0 ? -1 : wait4pid(G.pid);
353 }
354# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
355 }
356 else {
357 int idx;
358 status = !G.running_procs && !G.max_procs ? 0 : wait_for_slot(&idx);
359 if (G.max_procs) {
360 HANDLE p = (HANDLE)mingw_spawn_proc((const char **)G.args);
361 if (p < 0)
362 status = -1;
363 else
364 G.procs[idx] = p;
365 } else {
366 while (G.running_procs) {
367 int status2 = wait_for_slot(&idx);
368 if (status2 && !status)
369 status = status2;
370 }
371 }
372 }
373# endif
374#endif
243 /* Manpage: 375 /* Manpage:
244 * """xargs exits with the following status: 376 * """xargs exits with the following status:
245 * 0 if it succeeds 377 * 0 if it succeeds
@@ -278,8 +410,10 @@ static int xargs_exec(void)
278 ret: 410 ret:
279 if (status != 0) 411 if (status != 0)
280 G.xargs_exitcode = status; 412 G.xargs_exitcode = status;
413#if !ENABLE_PLATFORM_MINGW32
281 if (option_mask32 & OPT_STDIN_TTY) 414 if (option_mask32 & OPT_STDIN_TTY)
282 xdup2(G.fd_stdin, STDIN_FILENO); 415 xdup2(G.fd_stdin, STDIN_FILENO);
416#endif
283 return status; 417 return status;
284} 418}
285 419
@@ -559,6 +693,7 @@ static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg
559 */ 693 */
560static int xargs_ask_confirmation(void) 694static int xargs_ask_confirmation(void)
561{ 695{
696#if !ENABLE_PLATFORM_MINGW32
562 FILE *tty_stream; 697 FILE *tty_stream;
563 int r; 698 int r;
564 699
@@ -568,6 +703,18 @@ static int xargs_ask_confirmation(void)
568 r = bb_ask_y_confirmation_FILE(tty_stream); 703 r = bb_ask_y_confirmation_FILE(tty_stream);
569 704
570 fclose(tty_stream); 705 fclose(tty_stream);
706#else
707 int r, c, savec;
708
709 fputs(" ?...", stderr);
710 fflush_all();
711 c = savec = getche();
712 while (c != EOF && c != '\r')
713 c = getche();
714 fputs("\n", stderr);
715 fflush_all();
716 r = (savec == 'y' || savec == 'Y');
717#endif
571 718
572 return r; 719 return r;
573} 720}
@@ -575,6 +722,20 @@ static int xargs_ask_confirmation(void)
575# define xargs_ask_confirmation() 1 722# define xargs_ask_confirmation() 1
576#endif 723#endif
577 724
725#if ENABLE_PLATFORM_MINGW32
726// Maximum command length (less a few bytes)
727# define WIN32_MAX_CHARS (32750)
728
729static size_t quote_len(const char *arg)
730{
731 char *s = quote_arg(arg);
732 size_t len = strlen(s);
733
734 free(s);
735 return len;
736}
737#endif
738
578//usage:#define xargs_trivial_usage 739//usage:#define xargs_trivial_usage
579//usage: "[OPTIONS] [PROG ARGS]" 740//usage: "[OPTIONS] [PROG ARGS]"
580//usage:#define xargs_full_usage "\n\n" 741//usage:#define xargs_full_usage "\n\n"
@@ -585,7 +746,9 @@ static int xargs_ask_confirmation(void)
585//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( 746//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE(
586//usage: "\n -a FILE Read from FILE instead of stdin" 747//usage: "\n -a FILE Read from FILE instead of stdin"
587//usage: ) 748//usage: )
749//usage: IF_NOT_PLATFORM_MINGW32(
588//usage: "\n -o Reopen stdin as /dev/tty" 750//usage: "\n -o Reopen stdin as /dev/tty"
751//usage: )
589//usage: "\n -r Don't run command if input is empty" 752//usage: "\n -r Don't run command if input is empty"
590//usage: "\n -t Print the command on stderr before execution" 753//usage: "\n -t Print the command on stderr before execution"
591//usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION( 754//usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(
@@ -618,6 +781,11 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
618 unsigned opt; 781 unsigned opt;
619 int n_max_chars; 782 int n_max_chars;
620 int n_max_arg; 783 int n_max_arg;
784#if ENABLE_PLATFORM_MINGW32
785 int delta = 0;
786 int quote = TRUE;
787 char *old_buf = NULL;
788#endif
621#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \ 789#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \
622 || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 790 || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
623 char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin; 791 char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin;
@@ -628,6 +796,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
628 796
629 INIT_G(); 797 INIT_G();
630 798
799#if ENABLE_PLATFORM_MINGW32
800 SetConsoleCtrlHandler(ctrl_handler, TRUE);
801#endif
631 opt = getopt32long(argv, OPTION_STR, 802 opt = getopt32long(argv, OPTION_STR,
632 "no-run-if-empty\0" No_argument "r", 803 "no-run-if-empty\0" No_argument "r",
633 &max_args, &max_chars, &G.eof_str, &G.eof_str 804 &max_args, &max_chars, &G.eof_str, &G.eof_str
@@ -638,7 +809,12 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
638 809
639#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 810#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
640 if (G.max_procs <= 0) /* -P0 means "run lots of them" */ 811 if (G.max_procs <= 0) /* -P0 means "run lots of them" */
812#if !ENABLE_PLATFORM_MINGW32
641 G.max_procs = 100; /* let's not go crazy high */ 813 G.max_procs = 100; /* let's not go crazy high */
814#else
815 G.max_procs = MAXIMUM_WAIT_OBJECTS;
816 G.procs = xmalloc(sizeof(G.procs[0]) * G.max_procs);
817#endif
642#endif 818#endif
643 819
644#if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE 820#if ENABLE_FEATURE_XARGS_SUPPORT_ARGS_FILE
@@ -665,6 +841,24 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
665 //argc++; 841 //argc++;
666 } 842 }
667 843
844#if ENABLE_PLATFORM_MINGW32
845 /* On Windows the command line may be expanded by the need to quote
846 * arguments, but not if the command is a NOFORK applet. If the rules
847 * to detect this situation change xargs_exec() above will also need
848 * to be updated. */
849# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
850 if (G.max_procs == 1)
851# endif
852 {
853# if ENABLE_FEATURE_PREFER_APPLETS && (NUM_APPLETS > 1)
854 int applet = find_applet_by_name(argv[0]);
855 if (applet >= 0 && APPLET_IS_NOFORK(applet)) {
856 quote = FALSE;
857 }
858 }
859# endif
860#endif
861
668 /* 862 /*
669 * The Open Group Base Specifications Issue 6: 863 * The Open Group Base Specifications Issue 6:
670 * "The xargs utility shall limit the command line length such that 864 * "The xargs utility shall limit the command line length such that
@@ -689,7 +883,12 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
689 { 883 {
690 size_t n_chars = 0; 884 size_t n_chars = 0;
691 for (i = 0; argv[i]; i++) { 885 for (i = 0; argv[i]; i++) {
692 n_chars += strlen(argv[i]) + 1; 886#if ENABLE_PLATFORM_MINGW32
887 if (quote)
888 n_chars += quote_len(argv[i]) + 1;
889 else
890#endif
891 n_chars += strlen(argv[i]) + 1;
693 } 892 }
694 n_max_chars -= n_chars; 893 n_max_chars -= n_chars;
695 } 894 }
@@ -736,21 +935,48 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
736 store_param(argv[i]); 935 store_param(argv[i]);
737 } 936 }
738 937
938#if !ENABLE_PLATFORM_MINGW32
739 if (opt & OPT_STDIN_TTY) { 939 if (opt & OPT_STDIN_TTY) {
740 G.fd_tty = xopen(CURRENT_TTY, O_RDONLY); 940 G.fd_tty = xopen(CURRENT_TTY, O_RDONLY);
741 close_on_exec_on(G.fd_tty); 941 close_on_exec_on(G.fd_tty);
742 G.fd_stdin = dup(STDIN_FILENO); 942 G.fd_stdin = dup(STDIN_FILENO);
743 close_on_exec_on(G.fd_stdin); 943 close_on_exec_on(G.fd_stdin);
744 } 944 }
945#endif
745 946
746 initial_idx = G.idx; 947 initial_idx = G.idx;
747 while (1) { 948 while (1) {
748 char *rem; 949 char *rem;
950#if ENABLE_PLATFORM_MINGW32
951 char **args;
952 char **tail = NULL;
953 char *saved_arg = NULL;
954 size_t n_chars;
955#endif
749 956
750 G.idx = initial_idx; 957 G.idx = initial_idx IF_PLATFORM_MINGW32(+ delta);
751 rem = read_args(n_max_chars, n_max_arg, buf); 958 rem = read_args(n_max_chars, n_max_arg, buf);
752 store_param(NULL); 959 store_param(NULL);
753 960
961#if ENABLE_PLATFORM_MINGW32
962 /* Check if quoting expands the command line. If it does we
963 * truncate args[] and preserve the tail for processing later. */
964 args = G.args;
965 if (quote) {
966 skip_read:
967 n_chars = 0;
968 for (i = initial_idx; args[i]; i++) {
969 n_chars += quote_len(args[i]) + 1;
970 if (n_chars > WIN32_MAX_CHARS) {
971 tail = args + i;
972 saved_arg = *tail;
973 *tail = NULL;
974 break;
975 }
976 }
977 }
978#endif
979
754 if (!G.args[initial_idx]) { /* not even one ARG was added? */ 980 if (!G.args[initial_idx]) { /* not even one ARG was added? */
755 if (*rem != '\0') 981 if (*rem != '\0')
756 bb_simple_error_msg_and_die("argument line too long"); 982 bb_simple_error_msg_and_die("argument line too long");
@@ -761,7 +987,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
761 987
762 if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) { 988 if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) {
763 const char *fmt = " %s" + 1; 989 const char *fmt = " %s" + 1;
990#if !ENABLE_PLATFORM_MINGW32
764 char **args = G.args; 991 char **args = G.args;
992#endif
765 for (i = 0; args[i]; i++) { 993 for (i = 0; args[i]; i++) {
766 fprintf(stderr, fmt, args[i]); 994 fprintf(stderr, fmt, args[i]);
767 fmt = " %s"; 995 fmt = " %s";
@@ -775,6 +1003,33 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
775 break; /* G.xargs_exitcode is set by xargs_exec() */ 1003 break; /* G.xargs_exitcode is set by xargs_exec() */
776 } 1004 }
777 1005
1006#if ENABLE_PLATFORM_MINGW32
1007 delta = 0;
1008 if (quote && tail) {
1009 /* The command line was truncated. Preload args[] with
1010 * the tail we saved earlier. */
1011 *tail = saved_arg;
1012 n_chars = 0;
1013 for (i = 0; tail[i]; i++) {
1014 args[initial_idx + i] = tail[i];
1015 n_chars += quote_len(tail[i]) + 1;
1016 }
1017 args[initial_idx + i] = NULL;
1018 delta = i;
1019
1020 /* The command line still overflows after quoting.
1021 * Truncate the new args[] and exec it. */
1022 if (n_chars > WIN32_MAX_CHARS)
1023 goto skip_read;
1024
1025 /* The first elements of args[] point to strings in the
1026 * current buf, so we need to preserve it. Allocate a
1027 * new buf for future use. */
1028 free(old_buf);
1029 old_buf = buf;
1030 buf = xzalloc(n_max_chars + 1);
1031 }
1032#endif
778 overlapping_strcpy(buf, rem); 1033 overlapping_strcpy(buf, rem);
779 } /* while */ 1034 } /* while */
780 1035
@@ -782,6 +1037,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
782 free(G.args); 1037 free(G.args);
783 free(buf); 1038 free(buf);
784 } 1039 }
1040#if ENABLE_FEATURE_CLEAN_UP && ENABLE_PLATFORM_MINGW32
1041 free(old_buf);
1042#endif
785 1043
786#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 1044#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
787 G.max_procs = 0; 1045 G.max_procs = 0;