Don't check size_of_environment against arg_max since that causes the
[findutils.git] / xargs / xargs.c
blob3780d3fd8b0069e4c652321f75c23679c220fa61
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 <gnulib/config.h>
24 #undef VERSION
25 #undef PACKAGE_VERSION
26 #undef PACKAGE_TARNAME
27 #undef PACKAGE_STRING
28 #undef PACKAGE_NAME
29 #undef PACKAGE
30 #include <config.h>
32 # ifndef PARAMS
33 # if defined PROTOTYPES || (defined __STDC__ && __STDC__)
34 # define PARAMS(Args) Args
35 # else
36 # define PARAMS(Args) ()
37 # endif
38 # endif
40 #ifndef _GNU_SOURCE
41 #define _GNU_SOURCE
42 #endif
43 #include <ctype.h>
45 #if !defined (isascii) || defined (STDC_HEADERS)
46 #ifdef isascii
47 #undef isascii
48 #endif
49 #define isascii(c) 1
50 #endif
52 #ifdef isblank
53 #define ISBLANK(c) (isascii (c) && isblank (c))
54 #else
55 #define ISBLANK(c) ((c) == ' ' || (c) == '\t')
56 #endif
58 #define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \
59 || (c) == '\f' || (c) == '\v')
61 #include <sys/types.h>
62 #include <stdio.h>
63 #include <errno.h>
64 #include <getopt.h>
65 #include <fcntl.h>
67 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
68 #include <string.h>
69 #if !defined(STDC_HEADERS)
70 #include <memory.h>
71 #endif
72 #else
73 #include <strings.h>
74 #define memcpy(dest, source, count) (bcopy((source), (dest), (count)))
75 #endif
77 #ifndef _POSIX_SOURCE
78 #include <sys/param.h>
79 #endif
81 #ifdef HAVE_LIMITS_H
82 #include <limits.h>
83 #endif
85 #ifndef LONG_MAX
86 #define LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
87 #endif
89 #ifdef HAVE_UNISTD_H
90 #include <unistd.h>
91 #endif
93 #include <signal.h>
95 #if !defined(SIGCHLD) && defined(SIGCLD)
96 #define SIGCHLD SIGCLD
97 #endif
99 /* COMPAT: SYSV version defaults size (and has a max value of) to 470.
100 We try to make it as large as possible. */
101 #if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
102 #define ARG_MAX sysconf (_SC_ARG_MAX)
103 #endif
104 #ifndef ARG_MAX
105 #define ARG_MAX NCARGS
106 #endif
108 #include "wait.h"
110 /* States for read_line. */
111 #define NORM 0
112 #define SPACE 1
113 #define QUOTE 2
114 #define BACKSLASH 3
116 #ifdef STDC_HEADERS
117 #include <stdlib.h>
118 #else
119 extern int errno;
120 #endif
122 #ifdef HAVE_LOCALE_H
123 #include <locale.h>
124 #endif
125 #if ENABLE_NLS
126 # include <libintl.h>
127 # define _(Text) gettext (Text)
128 #else
129 # define _(Text) Text
130 #define textdomain(Domain)
131 #define bindtextdomain(Package, Directory)
132 #endif
133 #ifdef gettext_noop
134 # define N_(String) gettext_noop (String)
135 #else
136 # define N_(String) (String)
137 #endif
139 /* Return nonzero if S is the EOF string. */
140 #define EOF_STR(s) (eof_str && *eof_str == *s && !strcmp (eof_str, s))
142 extern char **environ;
144 /* Do multibyte processing if multibyte characters are supported,
145 unless multibyte sequences are search safe. Multibyte sequences
146 are search safe if searching for a substring using the byte
147 comparison function 'strstr' gives no false positives. All 8-bit
148 encodings and the UTF-8 multibyte encoding are search safe, but
149 the EUC encodings are not.
150 BeOS uses the UTF-8 encoding exclusively, so it is search safe. */
151 #if defined __BEOS__
152 # define MULTIBYTE_IS_SEARCH_SAFE 1
153 #endif
154 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_SEARCH_SAFE)
156 #if DO_MULTIBYTE
157 # if HAVE_MBRLEN
158 # include <wchar.h>
159 # else
160 /* Simulate mbrlen with mblen as best we can. */
161 # define mbstate_t int
162 # define mbrlen(s, n, ps) mblen (s, n)
163 # endif
164 #endif
166 /* Not char because of type promotion; NeXT gcc can't handle it. */
167 typedef int boolean;
168 #define true 1
169 #define false 0
171 #if __STDC__
172 #define VOID void
173 #else
174 #define VOID char
175 #endif
177 #include <xalloc.h>
178 void error PARAMS ((int status, int errnum, char *message,...));
180 extern char *version_string;
182 /* The name this program was run with. */
183 char *program_name;
185 /* Buffer for reading arguments from stdin. */
186 static char *linebuf;
188 /* Line number in stdin since the last command was executed. */
189 static int lineno = 0;
191 /* If nonzero, then instead of putting the args from stdin at
192 the end of the command argument list, they are each stuck into the
193 initial args, replacing each occurrence of the `replace_pat' in the
194 initial args. */
195 static char *replace_pat = NULL;
197 /* The length of `replace_pat'. */
198 static size_t rplen = 0;
200 /* If nonzero, when this string is read on stdin it is treated as
201 end of file.
202 I don't like this - it should default to NULL. */
203 static char *eof_str = "_";
205 /* If nonzero, the maximum number of nonblank lines from stdin to use
206 per command line. */
207 static long lines_per_exec = 0;
209 /* The maximum number of arguments to use per command line. */
210 static long args_per_exec = 1024;
212 /* If true, exit if lines_per_exec or args_per_exec is exceeded. */
213 static boolean exit_if_size_exceeded = false;
215 /* The maximum number of characters that can be used per command line. */
216 static long arg_max;
218 /* Storage for elements of `cmd_argv'. */
219 static char *argbuf;
221 /* The list of args being built. */
222 static char **cmd_argv = NULL;
224 /* Number of elements allocated for `cmd_argv'. */
225 static int cmd_argv_alloc = 0;
227 /* Number of valid elements in `cmd_argv'. */
228 static int cmd_argc = 0;
230 /* Number of chars being used in `cmd_argv'. */
231 static int cmd_argv_chars = 0;
233 /* Number of initial arguments given on the command line. */
234 static int initial_argc = 0;
236 /* Number of chars in the initial args. */
237 static int initial_argv_chars = 0;
239 /* true when building up initial arguments in `cmd_argv'. */
240 static boolean initial_args = true;
242 /* If nonzero, the maximum number of child processes that can be running
243 at once. */
244 static int proc_max = 1;
246 /* Total number of child processes that have been executed. */
247 static int procs_executed = 0;
249 /* The number of elements in `pids'. */
250 static int procs_executing = 0;
252 /* List of child processes currently executing. */
253 static pid_t *pids = NULL;
255 /* The number of allocated elements in `pids'. */
256 static int pids_alloc = 0;
258 /* Exit status; nonzero if any child process exited with a
259 status of 1-125. */
260 static int child_error = 0;
262 /* If true, print each command on stderr before executing it. */
263 static boolean print_command = false;
265 /* If true, query the user before executing each command, and only
266 execute the command if the user responds affirmatively. */
267 static boolean query_before_executing = false;
269 static struct option const longopts[] =
271 {"null", no_argument, NULL, '0'},
272 {"eof", optional_argument, NULL, 'e'},
273 {"replace", optional_argument, NULL, 'i'},
274 {"max-lines", optional_argument, NULL, 'l'},
275 {"max-args", required_argument, NULL, 'n'},
276 {"interactive", no_argument, NULL, 'p'},
277 {"no-run-if-empty", no_argument, NULL, 'r'},
278 {"max-chars", required_argument, NULL, 's'},
279 {"verbose", no_argument, NULL, 't'},
280 {"exit", no_argument, NULL, 'x'},
281 {"max-procs", required_argument, NULL, 'P'},
282 {"version", no_argument, NULL, 'v'},
283 {"help", no_argument, NULL, 'h'},
284 {NULL, no_argument, NULL, 0}
287 static int read_line PARAMS ((void));
288 static int read_string PARAMS ((void));
289 static char *mbstrstr PARAMS ((const char *haystack, const char *needle));
290 static void do_insert PARAMS ((char *arg, size_t arglen, size_t lblen));
291 static void push_arg PARAMS ((char *arg, size_t len));
292 static boolean print_args PARAMS ((boolean ask));
293 static void do_exec PARAMS ((void));
294 static void add_proc PARAMS ((pid_t pid));
295 static void wait_for_proc PARAMS ((boolean all));
296 static long parse_num PARAMS ((char *str, int option, long min, long max));
297 static long env_size PARAMS ((char **envp));
298 static void usage PARAMS ((FILE * stream, int status));
301 main (int argc, char **argv)
303 int optc;
304 int always_run_command = 1;
305 long orig_arg_max;
306 long arg_size;
307 long size_of_environment = env_size(environ);
308 char *default_cmd = "/bin/echo";
309 int (*read_args) PARAMS ((void)) = read_line;
311 program_name = argv[0];
313 #ifdef HAVE_SETLOCALE
314 setlocale (LC_ALL, "");
315 #endif
316 bindtextdomain (PACKAGE, LOCALEDIR);
317 textdomain (PACKAGE);
319 orig_arg_max = ARG_MAX;
320 if (orig_arg_max == -1)
321 orig_arg_max = LONG_MAX;
322 orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048. */
323 arg_max = orig_arg_max;
325 arg_size = 20 * 1048 + size_of_environment;
328 /* Take the size of the environment into account. */
329 arg_max -= env_size (environ);
330 if (arg_max <= 0)
331 error (1, 0, _("environment is too large for exec"));
333 while ((optc = getopt_long (argc, argv, "+0e::i::l::n:prs:txP:",
334 longopts, (int *) 0)) != -1)
336 switch (optc)
338 case '0':
339 read_args = read_string;
340 break;
342 case 'e':
343 if (optarg)
344 eof_str = optarg;
345 else
346 eof_str = 0;
347 break;
349 case 'h':
350 usage (stdout, 0);
352 case 'i':
353 if (optarg)
354 replace_pat = optarg;
355 else
356 replace_pat = "{}";
357 /* -i excludes -n -l. */
358 args_per_exec = 0;
359 lines_per_exec = 0;
360 break;
362 case 'l':
363 if (optarg)
364 lines_per_exec = parse_num (optarg, 'l', 1L, -1L);
365 else
366 lines_per_exec = 1;
367 /* -l excludes -i -n. */
368 args_per_exec = 0;
369 replace_pat = NULL;
370 break;
372 case 'n':
373 args_per_exec = parse_num (optarg, 'n', 1L, -1L);
374 /* -n excludes -i -l. */
375 lines_per_exec = 0;
376 if (args_per_exec == 1 && replace_pat)
377 /* ignore -n1 in '-i -n1' */
378 args_per_exec = 0;
379 else
380 replace_pat = NULL;
381 break;
383 case 's':
384 arg_size = parse_num (optarg, 's', 1L, orig_arg_max);
385 break;
387 case 't':
388 print_command = true;
389 break;
391 case 'x':
392 exit_if_size_exceeded = true;
393 break;
395 case 'p':
396 query_before_executing = true;
397 print_command = true;
398 break;
400 case 'r':
401 always_run_command = 0;
402 break;
404 case 'P':
405 proc_max = parse_num (optarg, 'P', 0L, -1L);
406 break;
408 case 'v':
409 printf (_("GNU xargs version %s\n"), version_string);
410 exit (0);
412 default:
413 usage (stderr, 1);
417 if (replace_pat || lines_per_exec)
418 exit_if_size_exceeded = true;
420 if (optind == argc)
422 optind = 0;
423 argc = 1;
424 argv = &default_cmd;
427 /* Taking into account the sisze of the environment,
428 * figure out how large a buffer we need to
429 * hold all the arguments. We cannot use ARG_MAX
430 * directly since that may be arbitrarily large.
431 * This is from a patch by Bob Prolux, <bob@proulx.com>.
433 if (arg_max > arg_size)
435 arg_max = arg_size;
438 linebuf = (char *) xmalloc (arg_max + 1);
439 argbuf = (char *) xmalloc (arg_max + 1);
441 /* Make sure to listen for the kids. */
442 signal (SIGCHLD, SIG_DFL);
444 if (!replace_pat)
446 for (; optind < argc; optind++)
447 push_arg (argv[optind], strlen (argv[optind]) + 1);
448 initial_args = false;
449 initial_argc = cmd_argc;
450 initial_argv_chars = cmd_argv_chars;
452 while ((*read_args) () != -1)
453 if (lines_per_exec && lineno >= lines_per_exec)
455 do_exec ();
456 lineno = 0;
459 /* SYSV xargs seems to do at least one exec, even if the
460 input is empty. */
461 if (cmd_argc != initial_argc
462 || (always_run_command && procs_executed == 0))
463 do_exec ();
465 else
467 int i;
468 size_t len;
469 size_t *arglen = (size_t *) xmalloc (sizeof (size_t) * argc);
471 for (i = optind; i < argc; i++)
472 arglen[i] = strlen(argv[i]);
473 rplen = strlen (replace_pat);
474 while ((len = (*read_args) ()) != -1)
476 /* Don't do insert on the command name. */
477 push_arg (argv[optind], arglen[optind] + 1);
478 len--;
479 for (i = optind + 1; i < argc; i++)
480 do_insert (argv[i], arglen[i], len);
481 do_exec ();
485 wait_for_proc (true);
486 exit (child_error);
489 #if 0
490 static int
491 append_char_to_buf(char **pbuf, char **pend, char **pp, int c)
493 char *end_of_buffer = *pend;
494 char *start_of_buffer = *pbuf;
495 char *p = *pp;
496 if (p >= end_of_buffer)
498 if (replace_pat)
500 size_t len = end_of_buffer - start_of_buffer;
501 size_t offset = p - start_of_buffer;
502 len *= 2;
503 start_of_buffer = xrealloc(start_of_buffer, len*2);
504 if (NULL != start_of_buffer)
506 end_of_buffer = start_of_buffer + len;
507 p = start_of_buffer + offset;
508 *p++ = c;
510 /* Update the caller's idea of where the buffer is. */
511 *pbuf = start_of_buffer;
512 *pend = end_of_buffer;
513 *pp = p;
515 return 0;
517 else
519 /* Failed to reallocate. */
520 return -1;
523 else
525 /* I suspect that this can never happen now, because append_char_to_buf()
526 * should only be called wen replace_pat is true.
528 error (1, 0, _("argument line too long"));
529 /*NOTREACHED*/
530 return -1;
533 else
535 /* Enough space remains. */
536 *p++ = c;
537 *pp = p;
538 return 0;
541 #endif
544 /* Read a line of arguments from stdin and add them to the list of
545 arguments to pass to the command. Ignore blank lines and initial blanks.
546 Single and double quotes and backslashes quote metacharacters and blanks
547 as they do in the shell.
548 Return -1 if eof (either physical or logical) is reached,
549 otherwise the length of the last string read (including the null). */
551 static int
552 read_line (void)
554 static boolean eof = false;
555 /* Start out in mode SPACE to always strip leading spaces (even with -i). */
556 int state = SPACE; /* The type of character we last read. */
557 int prevc; /* The previous value of c. */
558 int quotc = 0; /* The last quote character read. */
559 int c = EOF;
560 boolean first = true; /* true if reading first arg on line. */
561 int len;
562 char *p = linebuf;
563 /* Including the NUL, the args must not grow past this point. */
564 char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
566 if (eof)
567 return -1;
568 while (1)
570 prevc = c;
571 c = getc (stdin);
572 if (c == EOF)
574 /* COMPAT: SYSV seems to ignore stuff on a line that
575 ends without a \n; we don't. */
576 eof = true;
577 if (p == linebuf)
578 return -1;
579 *p++ = '\0';
580 len = p - linebuf;
581 /* FIXME we don't check for unterminated quotes here. */
582 if (first && EOF_STR (linebuf))
583 return -1;
584 if (!replace_pat)
585 push_arg (linebuf, len);
586 return len;
588 switch (state)
590 case SPACE:
591 if (ISSPACE (c))
592 continue;
593 state = NORM;
594 /* aaahhhh.... */
596 case NORM:
597 if (c == '\n')
599 if (!ISBLANK (prevc))
600 lineno++; /* For -l. */
601 if (p == linebuf)
603 /* Blank line. */
604 state = SPACE;
605 continue;
607 *p++ = '\0';
608 len = p - linebuf;
609 if (EOF_STR (linebuf))
611 eof = true;
612 return first ? -1 : len;
614 if (!replace_pat)
615 push_arg (linebuf, len);
616 return len;
618 if (!replace_pat && ISSPACE (c))
620 *p++ = '\0';
621 len = p - linebuf;
622 if (EOF_STR (linebuf))
624 eof = true;
625 return first ? -1 : len;
627 push_arg (linebuf, len);
628 p = linebuf;
629 state = SPACE;
630 first = false;
631 continue;
633 switch (c)
635 case '\\':
636 state = BACKSLASH;
637 continue;
639 case '\'':
640 case '"':
641 state = QUOTE;
642 quotc = c;
643 continue;
645 break;
647 case QUOTE:
648 if (c == '\n')
649 error (1, 0, _("unmatched %s quote"),
650 quotc == '"' ? _("double") : _("single"));
651 if (c == quotc)
653 state = NORM;
654 continue;
656 break;
658 case BACKSLASH:
659 state = NORM;
660 break;
662 #if 1
663 if (p >= endbuf)
664 error (1, 0, _("argument line too long"));
665 *p++ = c;
666 #else
667 append_char_to_buf(&linebuf, &endbuf, &p, c);
668 #endif
672 /* Read a null-terminated string from stdin and add it to the list of
673 arguments to pass to the command.
674 Return -1 if eof (either physical or logical) is reached,
675 otherwise the length of the string read (including the null). */
677 static int
678 read_string (void)
680 static boolean eof = false;
681 int len;
682 char *p = linebuf;
683 /* Including the NUL, the args must not grow past this point. */
684 char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
686 if (eof)
687 return -1;
688 while (1)
690 int c = getc (stdin);
691 if (c == EOF)
693 eof = true;
694 if (p == linebuf)
695 return -1;
696 *p++ = '\0';
697 len = p - linebuf;
698 if (!replace_pat)
699 push_arg (linebuf, len);
700 return len;
702 if (c == '\0')
704 lineno++; /* For -l. */
705 *p++ = '\0';
706 len = p - linebuf;
707 if (!replace_pat)
708 push_arg (linebuf, len);
709 return len;
711 if (p >= endbuf)
712 error (1, 0, _("argument line too long"));
713 *p++ = c;
717 /* Finds the first occurrence of the substring NEEDLE in the string
718 HAYSTACK. Both strings can be multibyte strings. */
720 static char *
721 mbstrstr (const char *haystack, const char *needle)
723 #if DO_MULTIBYTE
724 if (MB_CUR_MAX > 1)
726 size_t hlen = strlen (haystack);
727 size_t nlen = strlen (needle);
728 mbstate_t mbstate;
729 size_t step;
731 memset (&mbstate, 0, sizeof (mbstate_t));
732 while (hlen >= nlen)
734 if (memcmp (haystack, needle, nlen) == 0)
735 return (char *) haystack;
736 step = mbrlen (haystack, hlen, &mbstate);
737 if (step <= 0)
738 break;
739 haystack += step;
740 hlen -= step;
742 return NULL;
744 #endif
745 return strstr (haystack, needle);
748 /* Replace all instances of `replace_pat' in ARG with `linebuf',
749 and add the resulting string to the list of arguments for the command
750 to execute.
751 ARGLEN is the length of ARG, not including the null.
752 LBLEN is the length of `linebuf', not including the null.
754 COMPAT: insertions on the SYSV version are limited to 255 chars per line,
755 and a max of 5 occurrences of replace_pat in the initial-arguments.
756 Those restrictions do not exist here. */
758 static void
759 do_insert (char *arg, size_t arglen, size_t lblen)
761 /* Temporary copy of each arg with the replace pattern replaced by the
762 real arg. */
763 static char *insertbuf;
764 char *p;
765 int bytes_left = arg_max - 1; /* Bytes left on the command line. */
767 if (!insertbuf)
768 insertbuf = (char *) xmalloc (arg_max + 1);
769 p = insertbuf;
773 size_t len; /* Length in ARG before `replace_pat'. */
774 char *s = mbstrstr (arg, replace_pat);
775 if (s)
776 len = s - arg;
777 else
778 len = arglen;
779 bytes_left -= len;
780 if (bytes_left <= 0)
781 break;
783 strncpy (p, arg, len);
784 p += len;
785 arg += len;
786 arglen -= len;
788 if (s)
790 bytes_left -= lblen;
791 if (bytes_left <= 0)
792 break;
793 strcpy (p, linebuf);
794 arg += rplen;
795 arglen -= rplen;
796 p += lblen;
799 while (*arg);
800 if (*arg)
801 error (1, 0, _("command too long"));
802 *p++ = '\0';
803 push_arg (insertbuf, p - insertbuf);
806 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
807 to the command.
808 LEN is the length of ARG, including the terminating null.
809 If this brings the list up to its maximum size, execute the command. */
811 static void
812 push_arg (char *arg, size_t len)
814 if (arg)
816 if (cmd_argv_chars + len > arg_max)
818 if (initial_args || cmd_argc == initial_argc)
819 error (1, 0, _("can not fit single argument within argument list size limit"));
820 /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */
821 if (replace_pat
822 || (exit_if_size_exceeded &&
823 (lines_per_exec || args_per_exec)))
824 error (1, 0, _("argument list too long"));
825 do_exec ();
827 if (!initial_args && args_per_exec &&
828 cmd_argc - initial_argc == args_per_exec)
829 do_exec ();
832 if (cmd_argc >= cmd_argv_alloc)
834 if (!cmd_argv)
836 cmd_argv_alloc = 64;
837 cmd_argv = (char **) xmalloc (sizeof (char *) * cmd_argv_alloc);
839 else
841 cmd_argv_alloc *= 2;
842 cmd_argv = (char **) xrealloc (cmd_argv,
843 sizeof (char *) * cmd_argv_alloc);
847 if (!arg)
848 cmd_argv[cmd_argc++] = NULL;
849 else
851 cmd_argv[cmd_argc++] = argbuf + cmd_argv_chars;
852 strcpy (argbuf + cmd_argv_chars, arg);
853 cmd_argv_chars += len;
857 /* Print the arguments of the command to execute.
858 If ASK is nonzero, prompt the user for a response, and
859 if the user responds affirmatively, return true;
860 otherwise, return false. */
862 static boolean
863 print_args (boolean ask)
865 int i;
867 for (i = 0; i < cmd_argc - 1; i++)
868 fprintf (stderr, "%s ", cmd_argv[i]);
869 if (ask)
871 static FILE *tty_stream;
872 int c, savec;
874 if (!tty_stream)
876 tty_stream = fopen ("/dev/tty", "r");
877 if (!tty_stream)
878 error (1, errno, "/dev/tty");
880 fputs ("?...", stderr);
881 fflush (stderr);
882 c = savec = getc (tty_stream);
883 while (c != EOF && c != '\n')
884 c = getc (tty_stream);
885 if (savec == 'y' || savec == 'Y')
886 return true;
888 else
889 putc ('\n', stderr);
891 return false;
895 /* Close stdin and attach /dev/null to it.
896 * This resolves Savannah bug #3992.
898 static void
899 prep_child_for_exec (void)
901 const char inputfile[] = "/dev/null";
902 /* fprintf(stderr, "attaching stdin to /dev/null\n"); */
904 close(0);
905 if (open(inputfile, O_RDONLY) < 0)
907 /* This is not entirely fatal, since
908 * executing the child with a closed
909 * stdin is almost as good as executing it
910 * with its stdin attached to /dev/null.
912 error (0, errno, "%s", inputfile);
917 /* Execute the command that has been built in `cmd_argv'. This may involve
918 waiting for processes that were previously executed. */
920 static void
921 do_exec (void)
923 pid_t child;
925 push_arg ((char *) NULL, 0); /* Null terminate the arg list. */
926 if (!query_before_executing || print_args (true))
928 if (proc_max && procs_executing >= proc_max)
929 wait_for_proc (false);
930 if (!query_before_executing && print_command)
931 print_args (false);
932 /* If we run out of processes, wait for a child to return and
933 try again. */
934 while ((child = fork ()) < 0 && errno == EAGAIN && procs_executing)
935 wait_for_proc (false);
936 switch (child)
938 case -1:
939 error (1, errno, _("cannot fork"));
941 case 0: /* Child. */
942 prep_child_for_exec();
943 execvp (cmd_argv[0], cmd_argv);
944 error (0, errno, "%s", cmd_argv[0]);
945 _exit (errno == ENOENT ? 127 : 126);
947 add_proc (child);
950 cmd_argc = initial_argc;
951 cmd_argv_chars = initial_argv_chars;
954 /* Add the process with id PID to the list of processes that have
955 been executed. */
957 static void
958 add_proc (pid_t pid)
960 int i;
962 /* Find an empty slot. */
963 for (i = 0; i < pids_alloc && pids[i]; i++)
965 if (i == pids_alloc)
967 if (pids_alloc == 0)
969 pids_alloc = proc_max ? proc_max : 64;
970 pids = (pid_t *) xmalloc (sizeof (pid_t) * pids_alloc);
972 else
974 pids_alloc *= 2;
975 pids = (pid_t *) xrealloc (pids,
976 sizeof (pid_t) * pids_alloc);
978 memset (&pids[i], '\0', sizeof (pid_t) * (pids_alloc - i));
980 pids[i] = pid;
981 procs_executing++;
982 procs_executed++;
985 /* If ALL is true, wait for all child processes to finish;
986 otherwise, wait for one child process to finish.
987 Remove the processes that finish from the list of executing processes. */
989 static void
990 wait_for_proc (boolean all)
992 while (procs_executing)
994 int i, status;
998 pid_t pid;
1000 while ((pid = wait (&status)) == (pid_t) -1)
1001 if (errno != EINTR)
1002 error (1, errno, _("error waiting for child process"));
1004 /* Find the entry in `pids' for the child process
1005 that exited. */
1006 for (i = 0; i < pids_alloc && pid != pids[i]; i++)
1009 while (i == pids_alloc); /* A child died that we didn't start? */
1011 /* Remove the child from the list. */
1012 pids[i] = 0;
1013 procs_executing--;
1015 if (WEXITSTATUS (status) == 126 || WEXITSTATUS (status) == 127)
1016 exit (WEXITSTATUS (status)); /* Can't find or run the command. */
1017 if (WEXITSTATUS (status) == 255)
1018 error (124, 0, _("%s: exited with status 255; aborting"), cmd_argv[0]);
1019 if (WIFSTOPPED (status))
1020 error (125, 0, _("%s: stopped by signal %d"), cmd_argv[0], WSTOPSIG (status));
1021 if (WIFSIGNALED (status))
1022 error (125, 0, _("%s: terminated by signal %d"), cmd_argv[0], WTERMSIG (status));
1023 if (WEXITSTATUS (status) != 0)
1024 child_error = 123;
1026 if (!all)
1027 break;
1031 /* Return the value of the number represented in STR.
1032 OPTION is the command line option to which STR is the argument.
1033 If the value does not fall within the boundaries MIN and MAX,
1034 Print an error message mentioning OPTION and exit. */
1036 static long
1037 parse_num (char *str, int option, long int min, long int max)
1039 char *eptr;
1040 long val;
1042 val = strtol (str, &eptr, 10);
1043 if (eptr == str || *eptr)
1045 fprintf (stderr, _("%s: invalid number for -%c option\n"),
1046 program_name, option);
1047 usage (stderr, 1);
1049 else if (val < min)
1051 fprintf (stderr, _("%s: value for -%c option must be >= %ld\n"),
1052 program_name, option, min);
1053 usage (stderr, 1);
1055 else if (max >= 0 && val > max)
1057 fprintf (stderr, _("%s: value for -%c option must be < %ld\n"),
1058 program_name, option, max);
1059 usage (stderr, 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, int status)
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);
1089 exit (status);