Use gnulib-tool --import to import the gnulib code, rather than the odd way we were...
[findutils.git] / xargs / xargs.c
blob8e509936ff8534f16d8d4a82227043156efaa361
1 /* xargs -- build and execute command lines from standard input
2 Copyright (C) 1990, 91, 92, 93, 94, 2000,2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.
20 /* Written by Mike Rendell <michael@cs.mun.ca>
21 and David MacKenzie <djm@gnu.ai.mit.edu>. */
23 #include <config.h>
25 # ifndef PARAMS
26 # if defined PROTOTYPES || (defined __STDC__ && __STDC__)
27 # define PARAMS(Args) Args
28 # else
29 # define PARAMS(Args) ()
30 # endif
31 # endif
33 #ifndef _GNU_SOURCE
34 #define _GNU_SOURCE
35 #endif
36 #include <ctype.h>
38 #if !defined (isascii) || defined (STDC_HEADERS)
39 #ifdef isascii
40 #undef isascii
41 #endif
42 #define isascii(c) 1
43 #endif
45 #ifdef isblank
46 #define ISBLANK(c) (isascii (c) && isblank (c))
47 #else
48 #define ISBLANK(c) ((c) == ' ' || (c) == '\t')
49 #endif
51 #define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \
52 || (c) == '\f' || (c) == '\v')
54 #include <sys/types.h>
55 #include <stdio.h>
56 #include <errno.h>
57 #include <getopt.h>
58 #include <fcntl.h>
60 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
61 #include <string.h>
62 #if !defined(STDC_HEADERS)
63 #include <memory.h>
64 #endif
65 #else
66 #include <strings.h>
67 #define memcpy(dest, source, count) (bcopy((source), (dest), (count)))
68 #endif
70 #ifndef _POSIX_SOURCE
71 #include <sys/param.h>
72 #endif
74 #ifdef HAVE_LIMITS_H
75 #include <limits.h>
76 #endif
78 #ifndef LONG_MAX
79 #define LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
80 #endif
82 #ifdef HAVE_UNISTD_H
83 #include <unistd.h>
84 #endif
86 #include <signal.h>
88 #if !defined(SIGCHLD) && defined(SIGCLD)
89 #define SIGCHLD SIGCLD
90 #endif
92 /* COMPAT: SYSV version defaults size (and has a max value of) to 470.
93 We try to make it as large as possible. */
94 #if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
95 #define ARG_MAX sysconf (_SC_ARG_MAX)
96 #endif
97 #ifndef ARG_MAX
98 #define ARG_MAX NCARGS
99 #endif
101 #include "wait.h"
103 /* States for read_line. */
104 #define NORM 0
105 #define SPACE 1
106 #define QUOTE 2
107 #define BACKSLASH 3
109 #ifdef STDC_HEADERS
110 #include <stdlib.h>
111 #else
112 extern int errno;
113 #endif
115 #ifdef HAVE_LOCALE_H
116 #include <locale.h>
117 #endif
118 #if ENABLE_NLS
119 # include <libintl.h>
120 # define _(Text) gettext (Text)
121 #else
122 # define _(Text) Text
123 #define textdomain(Domain)
124 #define bindtextdomain(Package, Directory)
125 #endif
126 #ifdef gettext_noop
127 # define N_(String) gettext_noop (String)
128 #else
129 /* See locate.c for explanation as to why not use (String) */
130 # define N_(String) String
131 #endif
133 /* Return nonzero if S is the EOF string. */
134 #define EOF_STR(s) (eof_str && *eof_str == *s && !strcmp (eof_str, s))
136 extern char **environ;
138 /* Do multibyte processing if multibyte characters are supported,
139 unless multibyte sequences are search safe. Multibyte sequences
140 are search safe if searching for a substring using the byte
141 comparison function 'strstr' gives no false positives. All 8-bit
142 encodings and the UTF-8 multibyte encoding are search safe, but
143 the EUC encodings are not.
144 BeOS uses the UTF-8 encoding exclusively, so it is search safe. */
145 #if defined __BEOS__
146 # define MULTIBYTE_IS_SEARCH_SAFE 1
147 #endif
148 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_SEARCH_SAFE)
150 #if DO_MULTIBYTE
151 # if HAVE_MBRLEN
152 # include <wchar.h>
153 # else
154 /* Simulate mbrlen with mblen as best we can. */
155 # define mbstate_t int
156 # define mbrlen(s, n, ps) mblen (s, n)
157 # endif
158 #endif
160 /* Not char because of type promotion; NeXT gcc can't handle it. */
161 typedef int boolean;
162 #define true 1
163 #define false 0
165 #if __STDC__
166 #define VOID void
167 #else
168 #define VOID char
169 #endif
171 #include <xalloc.h>
172 void error PARAMS ((int status, int errnum, char *message,...));
174 extern char *version_string;
176 /* The name this program was run with. */
177 char *program_name;
179 /* Buffer for reading arguments from stdin. */
180 static char *linebuf;
182 /* Line number in stdin since the last command was executed. */
183 static int lineno = 0;
185 /* If nonzero, then instead of putting the args from stdin at
186 the end of the command argument list, they are each stuck into the
187 initial args, replacing each occurrence of the `replace_pat' in the
188 initial args. */
189 static char *replace_pat = NULL;
191 /* The length of `replace_pat'. */
192 static size_t rplen = 0;
194 /* If nonzero, when this string is read on stdin it is treated as
195 end of file.
196 I don't like this - it should default to NULL. */
197 static char *eof_str = "_";
199 /* If nonzero, the maximum number of nonblank lines from stdin to use
200 per command line. */
201 static long lines_per_exec = 0;
203 /* The maximum number of arguments to use per command line. */
204 static long args_per_exec = 1024;
206 /* If true, exit if lines_per_exec or args_per_exec is exceeded. */
207 static boolean exit_if_size_exceeded = false;
209 /* The maximum number of characters that can be used per command line. */
210 static long arg_max;
212 /* Storage for elements of `cmd_argv'. */
213 static char *argbuf;
215 /* The list of args being built. */
216 static char **cmd_argv = NULL;
218 /* Number of elements allocated for `cmd_argv'. */
219 static int cmd_argv_alloc = 0;
221 /* Number of valid elements in `cmd_argv'. */
222 static int cmd_argc = 0;
224 /* Number of chars being used in `cmd_argv'. */
225 static int cmd_argv_chars = 0;
227 /* Number of initial arguments given on the command line. */
228 static int initial_argc = 0;
230 /* Number of chars in the initial args. */
231 static int initial_argv_chars = 0;
233 /* true when building up initial arguments in `cmd_argv'. */
234 static boolean initial_args = true;
236 /* If nonzero, the maximum number of child processes that can be running
237 at once. */
238 static int proc_max = 1;
240 /* Total number of child processes that have been executed. */
241 static int procs_executed = 0;
243 /* The number of elements in `pids'. */
244 static int procs_executing = 0;
246 /* List of child processes currently executing. */
247 static pid_t *pids = NULL;
249 /* The number of allocated elements in `pids'. */
250 static int pids_alloc = 0;
252 /* Exit status; nonzero if any child process exited with a
253 status of 1-125. */
254 static int child_error = 0;
256 /* If true, print each command on stderr before executing it. */
257 static boolean print_command = false;
259 /* If true, query the user before executing each command, and only
260 execute the command if the user responds affirmatively. */
261 static boolean query_before_executing = false;
263 static struct option const longopts[] =
265 {"null", no_argument, NULL, '0'},
266 {"eof", optional_argument, NULL, 'e'},
267 {"replace", optional_argument, NULL, 'i'},
268 {"max-lines", optional_argument, NULL, 'l'},
269 {"max-args", required_argument, NULL, 'n'},
270 {"interactive", no_argument, NULL, 'p'},
271 {"no-run-if-empty", no_argument, NULL, 'r'},
272 {"max-chars", required_argument, NULL, 's'},
273 {"verbose", no_argument, NULL, 't'},
274 {"exit", no_argument, NULL, 'x'},
275 {"max-procs", required_argument, NULL, 'P'},
276 {"version", no_argument, NULL, 'v'},
277 {"help", no_argument, NULL, 'h'},
278 {NULL, no_argument, NULL, 0}
281 static int read_line PARAMS ((void));
282 static int read_string PARAMS ((void));
283 static char *mbstrstr PARAMS ((const char *haystack, const char *needle));
284 static void do_insert PARAMS ((char *arg, size_t arglen, size_t lblen));
285 static void push_arg PARAMS ((char *arg, size_t len));
286 static boolean print_args PARAMS ((boolean ask));
287 static void do_exec PARAMS ((void));
288 static void add_proc PARAMS ((pid_t pid));
289 static void wait_for_proc PARAMS ((boolean all));
290 static long parse_num PARAMS ((char *str, int option, long min, long max));
291 static long env_size PARAMS ((char **envp));
292 static void usage PARAMS ((FILE * stream));
295 main (int argc, char **argv)
297 int optc;
298 int always_run_command = 1;
299 long orig_arg_max;
300 long arg_size;
301 long size_of_environment = env_size(environ);
302 char *default_cmd = "/bin/echo";
303 int (*read_args) PARAMS ((void)) = read_line;
305 program_name = argv[0];
307 #ifdef HAVE_SETLOCALE
308 setlocale (LC_ALL, "");
309 #endif
310 bindtextdomain (PACKAGE, LOCALEDIR);
311 textdomain (PACKAGE);
313 orig_arg_max = ARG_MAX;
314 if (orig_arg_max == -1)
315 orig_arg_max = LONG_MAX;
316 orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048. */
317 arg_max = orig_arg_max;
319 arg_size = 20 * 1048 + size_of_environment;
322 /* Take the size of the environment into account. */
323 arg_max -= env_size (environ);
324 if (arg_max <= 0)
325 error (1, 0, _("environment is too large for exec"));
327 while ((optc = getopt_long (argc, argv, "+0e::i::l::n:prs:txP:",
328 longopts, (int *) 0)) != -1)
330 switch (optc)
332 case '0':
333 read_args = read_string;
334 break;
336 case 'e':
337 if (optarg)
338 eof_str = optarg;
339 else
340 eof_str = 0;
341 break;
343 case 'h':
344 usage (stdout);
345 return 0;
347 case 'i':
348 if (optarg)
349 replace_pat = optarg;
350 else
351 replace_pat = "{}";
352 /* -i excludes -n -l. */
353 args_per_exec = 0;
354 lines_per_exec = 0;
355 break;
357 case 'l':
358 if (optarg)
359 lines_per_exec = parse_num (optarg, 'l', 1L, -1L);
360 else
361 lines_per_exec = 1;
362 /* -l excludes -i -n. */
363 args_per_exec = 0;
364 replace_pat = NULL;
365 break;
367 case 'n':
368 args_per_exec = parse_num (optarg, 'n', 1L, -1L);
369 /* -n excludes -i -l. */
370 lines_per_exec = 0;
371 if (args_per_exec == 1 && replace_pat)
372 /* ignore -n1 in '-i -n1' */
373 args_per_exec = 0;
374 else
375 replace_pat = NULL;
376 break;
378 case 's':
379 arg_size = parse_num (optarg, 's', 1L, orig_arg_max);
380 break;
382 case 't':
383 print_command = true;
384 break;
386 case 'x':
387 exit_if_size_exceeded = true;
388 break;
390 case 'p':
391 query_before_executing = true;
392 print_command = true;
393 break;
395 case 'r':
396 always_run_command = 0;
397 break;
399 case 'P':
400 proc_max = parse_num (optarg, 'P', 0L, -1L);
401 break;
403 case 'v':
404 printf (_("GNU xargs version %s\n"), version_string);
405 return 0;
407 default:
408 usage (stderr);
409 return 1;
413 if (replace_pat || lines_per_exec)
414 exit_if_size_exceeded = true;
416 if (optind == argc)
418 optind = 0;
419 argc = 1;
420 argv = &default_cmd;
423 /* Taking into account the sisze of the environment,
424 * figure out how large a buffer we need to
425 * hold all the arguments. We cannot use ARG_MAX
426 * directly since that may be arbitrarily large.
427 * This is from a patch by Bob Prolux, <bob@proulx.com>.
429 if (arg_max > arg_size)
431 arg_max = arg_size;
434 linebuf = (char *) xmalloc (arg_max + 1);
435 argbuf = (char *) xmalloc (arg_max + 1);
437 /* Make sure to listen for the kids. */
438 signal (SIGCHLD, SIG_DFL);
440 if (!replace_pat)
442 for (; optind < argc; optind++)
443 push_arg (argv[optind], strlen (argv[optind]) + 1);
444 initial_args = false;
445 initial_argc = cmd_argc;
446 initial_argv_chars = cmd_argv_chars;
448 while ((*read_args) () != -1)
449 if (lines_per_exec && lineno >= lines_per_exec)
451 do_exec ();
452 lineno = 0;
455 /* SYSV xargs seems to do at least one exec, even if the
456 input is empty. */
457 if (cmd_argc != initial_argc
458 || (always_run_command && procs_executed == 0))
459 do_exec ();
461 else
463 int i;
464 size_t len;
465 size_t *arglen = (size_t *) xmalloc (sizeof (size_t) * argc);
467 for (i = optind; i < argc; i++)
468 arglen[i] = strlen(argv[i]);
469 rplen = strlen (replace_pat);
470 while ((len = (*read_args) ()) != -1)
472 /* Don't do insert on the command name. */
473 push_arg (argv[optind], arglen[optind] + 1);
474 len--;
475 for (i = optind + 1; i < argc; i++)
476 do_insert (argv[i], arglen[i], len);
477 do_exec ();
481 wait_for_proc (true);
482 return child_error;
485 #if 0
486 static int
487 append_char_to_buf(char **pbuf, char **pend, char **pp, int c)
489 char *end_of_buffer = *pend;
490 char *start_of_buffer = *pbuf;
491 char *p = *pp;
492 if (p >= end_of_buffer)
494 if (replace_pat)
496 size_t len = end_of_buffer - start_of_buffer;
497 size_t offset = p - start_of_buffer;
498 len *= 2;
499 start_of_buffer = xrealloc(start_of_buffer, len*2);
500 if (NULL != start_of_buffer)
502 end_of_buffer = start_of_buffer + len;
503 p = start_of_buffer + offset;
504 *p++ = c;
506 /* Update the caller's idea of where the buffer is. */
507 *pbuf = start_of_buffer;
508 *pend = end_of_buffer;
509 *pp = p;
511 return 0;
513 else
515 /* Failed to reallocate. */
516 return -1;
519 else
521 /* I suspect that this can never happen now, because append_char_to_buf()
522 * should only be called wen replace_pat is true.
524 error (1, 0, _("argument line too long"));
525 /*NOTREACHED*/
526 return -1;
529 else
531 /* Enough space remains. */
532 *p++ = c;
533 *pp = p;
534 return 0;
537 #endif
540 /* Read a line of arguments from stdin and add them to the list of
541 arguments to pass to the command. Ignore blank lines and initial blanks.
542 Single and double quotes and backslashes quote metacharacters and blanks
543 as they do in the shell.
544 Return -1 if eof (either physical or logical) is reached,
545 otherwise the length of the last string read (including the null). */
547 static int
548 read_line (void)
550 static boolean eof = false;
551 /* Start out in mode SPACE to always strip leading spaces (even with -i). */
552 int state = SPACE; /* The type of character we last read. */
553 int prevc; /* The previous value of c. */
554 int quotc = 0; /* The last quote character read. */
555 int c = EOF;
556 boolean first = true; /* true if reading first arg on line. */
557 int len;
558 char *p = linebuf;
559 /* Including the NUL, the args must not grow past this point. */
560 char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
562 if (eof)
563 return -1;
564 while (1)
566 prevc = c;
567 c = getc (stdin);
568 if (c == EOF)
570 /* COMPAT: SYSV seems to ignore stuff on a line that
571 ends without a \n; we don't. */
572 eof = true;
573 if (p == linebuf)
574 return -1;
575 *p++ = '\0';
576 len = p - linebuf;
577 /* FIXME we don't check for unterminated quotes here. */
578 if (first && EOF_STR (linebuf))
579 return -1;
580 if (!replace_pat)
581 push_arg (linebuf, len);
582 return len;
584 switch (state)
586 case SPACE:
587 if (ISSPACE (c))
588 continue;
589 state = NORM;
590 /* aaahhhh.... */
592 case NORM:
593 if (c == '\n')
595 if (!ISBLANK (prevc))
596 lineno++; /* For -l. */
597 if (p == linebuf)
599 /* Blank line. */
600 state = SPACE;
601 continue;
603 *p++ = '\0';
604 len = p - linebuf;
605 if (EOF_STR (linebuf))
607 eof = true;
608 return first ? -1 : len;
610 if (!replace_pat)
611 push_arg (linebuf, len);
612 return len;
614 if (!replace_pat && ISSPACE (c))
616 *p++ = '\0';
617 len = p - linebuf;
618 if (EOF_STR (linebuf))
620 eof = true;
621 return first ? -1 : len;
623 push_arg (linebuf, len);
624 p = linebuf;
625 state = SPACE;
626 first = false;
627 continue;
629 switch (c)
631 case '\\':
632 state = BACKSLASH;
633 continue;
635 case '\'':
636 case '"':
637 state = QUOTE;
638 quotc = c;
639 continue;
641 break;
643 case QUOTE:
644 if (c == '\n')
645 error (1, 0, _("unmatched %s quote; by default quotes are special to xargs unless you use the -0 option"),
646 quotc == '"' ? _("double") : _("single"));
647 if (c == quotc)
649 state = NORM;
650 continue;
652 break;
654 case BACKSLASH:
655 state = NORM;
656 break;
658 #if 1
659 if (p >= endbuf)
660 error (1, 0, _("argument line too long"));
661 *p++ = c;
662 #else
663 append_char_to_buf(&linebuf, &endbuf, &p, c);
664 #endif
668 /* Read a null-terminated string from stdin and add it to the list of
669 arguments to pass to the command.
670 Return -1 if eof (either physical or logical) is reached,
671 otherwise the length of the string read (including the null). */
673 static int
674 read_string (void)
676 static boolean eof = false;
677 int len;
678 char *p = linebuf;
679 /* Including the NUL, the args must not grow past this point. */
680 char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
682 if (eof)
683 return -1;
684 while (1)
686 int c = getc (stdin);
687 if (c == EOF)
689 eof = true;
690 if (p == linebuf)
691 return -1;
692 *p++ = '\0';
693 len = p - linebuf;
694 if (!replace_pat)
695 push_arg (linebuf, len);
696 return len;
698 if (c == '\0')
700 lineno++; /* For -l. */
701 *p++ = '\0';
702 len = p - linebuf;
703 if (!replace_pat)
704 push_arg (linebuf, len);
705 return len;
707 if (p >= endbuf)
708 error (1, 0, _("argument line too long"));
709 *p++ = c;
713 /* Finds the first occurrence of the substring NEEDLE in the string
714 HAYSTACK. Both strings can be multibyte strings. */
716 static char *
717 mbstrstr (const char *haystack, const char *needle)
719 #if DO_MULTIBYTE
720 if (MB_CUR_MAX > 1)
722 size_t hlen = strlen (haystack);
723 size_t nlen = strlen (needle);
724 mbstate_t mbstate;
725 size_t step;
727 memset (&mbstate, 0, sizeof (mbstate_t));
728 while (hlen >= nlen)
730 if (memcmp (haystack, needle, nlen) == 0)
731 return (char *) haystack;
732 step = mbrlen (haystack, hlen, &mbstate);
733 if (step <= 0)
734 break;
735 haystack += step;
736 hlen -= step;
738 return NULL;
740 #endif
741 return strstr (haystack, needle);
744 /* Replace all instances of `replace_pat' in ARG with `linebuf',
745 and add the resulting string to the list of arguments for the command
746 to execute.
747 ARGLEN is the length of ARG, not including the null.
748 LBLEN is the length of `linebuf', not including the null.
750 COMPAT: insertions on the SYSV version are limited to 255 chars per line,
751 and a max of 5 occurrences of replace_pat in the initial-arguments.
752 Those restrictions do not exist here. */
754 static void
755 do_insert (char *arg, size_t arglen, size_t lblen)
757 /* Temporary copy of each arg with the replace pattern replaced by the
758 real arg. */
759 static char *insertbuf;
760 char *p;
761 int bytes_left = arg_max - 1; /* Bytes left on the command line. */
763 if (!insertbuf)
764 insertbuf = (char *) xmalloc (arg_max + 1);
765 p = insertbuf;
769 size_t len; /* Length in ARG before `replace_pat'. */
770 char *s = mbstrstr (arg, replace_pat);
771 if (s)
772 len = s - arg;
773 else
774 len = arglen;
775 bytes_left -= len;
776 if (bytes_left <= 0)
777 break;
779 strncpy (p, arg, len);
780 p += len;
781 arg += len;
782 arglen -= len;
784 if (s)
786 bytes_left -= lblen;
787 if (bytes_left <= 0)
788 break;
789 strcpy (p, linebuf);
790 arg += rplen;
791 arglen -= rplen;
792 p += lblen;
795 while (*arg);
796 if (*arg)
797 error (1, 0, _("command too long"));
798 *p++ = '\0';
799 push_arg (insertbuf, p - insertbuf);
802 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
803 to the command.
804 LEN is the length of ARG, including the terminating null.
805 If this brings the list up to its maximum size, execute the command. */
807 static void
808 push_arg (char *arg, size_t len)
810 if (arg)
812 if (cmd_argv_chars + len > arg_max)
814 if (initial_args || cmd_argc == initial_argc)
815 error (1, 0, _("can not fit single argument within argument list size limit"));
816 /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */
817 if (replace_pat
818 || (exit_if_size_exceeded &&
819 (lines_per_exec || args_per_exec)))
820 error (1, 0, _("argument list too long"));
821 do_exec ();
823 if (!initial_args && args_per_exec &&
824 cmd_argc - initial_argc == args_per_exec)
825 do_exec ();
828 if (cmd_argc >= cmd_argv_alloc)
830 if (!cmd_argv)
832 cmd_argv_alloc = 64;
833 cmd_argv = (char **) xmalloc (sizeof (char *) * cmd_argv_alloc);
835 else
837 cmd_argv_alloc *= 2;
838 cmd_argv = (char **) xrealloc (cmd_argv,
839 sizeof (char *) * cmd_argv_alloc);
843 if (!arg)
844 cmd_argv[cmd_argc++] = NULL;
845 else
847 cmd_argv[cmd_argc++] = argbuf + cmd_argv_chars;
848 strcpy (argbuf + cmd_argv_chars, arg);
849 cmd_argv_chars += len;
853 /* Print the arguments of the command to execute.
854 If ASK is nonzero, prompt the user for a response, and
855 if the user responds affirmatively, return true;
856 otherwise, return false. */
858 static boolean
859 print_args (boolean ask)
861 int i;
863 for (i = 0; i < cmd_argc - 1; i++)
864 fprintf (stderr, "%s ", cmd_argv[i]);
865 if (ask)
867 static FILE *tty_stream;
868 int c, savec;
870 if (!tty_stream)
872 tty_stream = fopen ("/dev/tty", "r");
873 if (!tty_stream)
874 error (1, errno, "/dev/tty");
876 fputs ("?...", stderr);
877 fflush (stderr);
878 c = savec = getc (tty_stream);
879 while (c != EOF && c != '\n')
880 c = getc (tty_stream);
881 if (savec == 'y' || savec == 'Y')
882 return true;
884 else
885 putc ('\n', stderr);
887 return false;
891 /* Close stdin and attach /dev/null to it.
892 * This resolves Savannah bug #3992.
894 static void
895 prep_child_for_exec (void)
897 const char inputfile[] = "/dev/null";
898 /* fprintf(stderr, "attaching stdin to /dev/null\n"); */
900 close(0);
901 if (open(inputfile, O_RDONLY) < 0)
903 /* This is not entirely fatal, since
904 * executing the child with a closed
905 * stdin is almost as good as executing it
906 * with its stdin attached to /dev/null.
908 error (0, errno, "%s", inputfile);
913 /* Execute the command that has been built in `cmd_argv'. This may involve
914 waiting for processes that were previously executed. */
916 static void
917 do_exec (void)
919 pid_t child;
921 push_arg ((char *) NULL, 0); /* Null terminate the arg list. */
922 if (!query_before_executing || print_args (true))
924 if (proc_max && procs_executing >= proc_max)
925 wait_for_proc (false);
926 if (!query_before_executing && print_command)
927 print_args (false);
928 /* If we run out of processes, wait for a child to return and
929 try again. */
930 while ((child = fork ()) < 0 && errno == EAGAIN && procs_executing)
931 wait_for_proc (false);
932 switch (child)
934 case -1:
935 error (1, errno, _("cannot fork"));
937 case 0: /* Child. */
938 prep_child_for_exec();
939 execvp (cmd_argv[0], cmd_argv);
940 error (0, errno, "%s", cmd_argv[0]);
941 _exit (errno == ENOENT ? 127 : 126);
942 /*NOTREACHED*/
944 add_proc (child);
947 cmd_argc = initial_argc;
948 cmd_argv_chars = initial_argv_chars;
951 /* Add the process with id PID to the list of processes that have
952 been executed. */
954 static void
955 add_proc (pid_t pid)
957 int i;
959 /* Find an empty slot. */
960 for (i = 0; i < pids_alloc && pids[i]; i++)
962 if (i == pids_alloc)
964 if (pids_alloc == 0)
966 pids_alloc = proc_max ? proc_max : 64;
967 pids = (pid_t *) xmalloc (sizeof (pid_t) * pids_alloc);
969 else
971 pids_alloc *= 2;
972 pids = (pid_t *) xrealloc (pids,
973 sizeof (pid_t) * pids_alloc);
975 memset (&pids[i], '\0', sizeof (pid_t) * (pids_alloc - i));
977 pids[i] = pid;
978 procs_executing++;
979 procs_executed++;
982 /* If ALL is true, wait for all child processes to finish;
983 otherwise, wait for one child process to finish.
984 Remove the processes that finish from the list of executing processes. */
986 static void
987 wait_for_proc (boolean all)
989 while (procs_executing)
991 int i, status;
995 pid_t pid;
997 while ((pid = wait (&status)) == (pid_t) -1)
998 if (errno != EINTR)
999 error (1, errno, _("error waiting for child process"));
1001 /* Find the entry in `pids' for the child process
1002 that exited. */
1003 for (i = 0; i < pids_alloc && pid != pids[i]; i++)
1006 while (i == pids_alloc); /* A child died that we didn't start? */
1008 /* Remove the child from the list. */
1009 pids[i] = 0;
1010 procs_executing--;
1012 if (WEXITSTATUS (status) == 126 || WEXITSTATUS (status) == 127)
1013 exit (WEXITSTATUS (status)); /* Can't find or run the command. */
1014 if (WEXITSTATUS (status) == 255)
1015 error (124, 0, _("%s: exited with status 255; aborting"), cmd_argv[0]);
1016 if (WIFSTOPPED (status))
1017 error (125, 0, _("%s: stopped by signal %d"), cmd_argv[0], WSTOPSIG (status));
1018 if (WIFSIGNALED (status))
1019 error (125, 0, _("%s: terminated by signal %d"), cmd_argv[0], WTERMSIG (status));
1020 if (WEXITSTATUS (status) != 0)
1021 child_error = 123;
1023 if (!all)
1024 break;
1028 /* Return the value of the number represented in STR.
1029 OPTION is the command line option to which STR is the argument.
1030 If the value does not fall within the boundaries MIN and MAX,
1031 Print an error message mentioning OPTION and exit. */
1033 static long
1034 parse_num (char *str, int option, long int min, long int max)
1036 char *eptr;
1037 long val;
1039 val = strtol (str, &eptr, 10);
1040 if (eptr == str || *eptr)
1042 fprintf (stderr, _("%s: invalid number for -%c option\n"),
1043 program_name, option);
1044 usage (stderr);
1045 exit(1);
1047 else if (val < min)
1049 fprintf (stderr, _("%s: value for -%c option must be >= %ld\n"),
1050 program_name, option, min);
1051 usage (stderr);
1052 exit(1);
1054 else if (max >= 0 && val > max)
1056 fprintf (stderr, _("%s: value for -%c option must be < %ld\n"),
1057 program_name, option, max);
1058 usage (stderr);
1059 exit(1);
1061 return val;
1064 /* Return how much of ARG_MAX is used by the environment. */
1066 static long
1067 env_size (char **envp)
1069 long len = 0;
1071 while (*envp)
1072 len += strlen (*envp++) + 1;
1074 return len;
1077 static void
1078 usage (FILE *stream)
1080 fprintf (stream, _("\
1081 Usage: %s [-0prtx] [-e[eof-str]] [-i[replace-str]] [-l[max-lines]]\n\
1082 [-n max-args] [-s max-chars] [-P max-procs] [--null] [--eof[=eof-str]]\n\
1083 [--replace[=replace-str]] [--max-lines[=max-lines]] [--interactive]\n\
1084 [--max-chars=max-chars] [--verbose] [--exit] [--max-procs=max-procs]\n\
1085 [--max-args=max-args] [--no-run-if-empty] [--version] [--help]\n\
1086 [command [initial-arguments]]\n"),
1087 program_name);
1088 fputs (_("\nReport bugs to <bug-findutils@gnu.org>.\n"), stream);