73b1a023755b00c32fb944dc656b305878e841a8
[oweals/busybox.git] / findutils / xargs.c
1 /* xargs for busybox */
2
3 /* xargs -- build and execute command lines from standard input
4    Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /* Written by Mike Rendell <michael@cs.mun.ca>
21    and David MacKenzie <djm@gnu.ai.mit.edu>.  */
22
23 #include "internal.h"
24
25 #define HAVE_STRING_H 1
26 #define HAVE_SYS_WAIT_H 1
27 #define HAVE_UNISTD_H 1
28 #define HAVE_LIMITS_H 1
29 #define STDC_HEADERS 1
30
31 #include <sys/types.h>          /* For pid_t. */
32 #if HAVE_SYS_WAIT_H
33 #include <sys/wait.h>
34 #endif
35
36 #ifndef WIFSTOPPED
37 #define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
38 #endif
39 #ifndef WIFSIGNALED
40 #define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
41 #endif
42 #ifndef WIFEXITED
43 #define WIFEXITED(w) (((w) & 0xff) == 0)
44 #endif
45
46 #ifndef WSTOPSIG
47 #define WSTOPSIG(w) (((w) >> 8) & 0xff)
48 #endif
49 #ifndef WTERMSIG
50 #define WTERMSIG(w) ((w) & 0x7f)
51 #endif
52 #ifndef WEXITSTATUS
53 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
54 #endif
55
56 #if __STDC__
57 #define P_(s) s
58 #else
59 #define P_(s) ()
60 #endif
61
62 #include <ctype.h>
63
64 #if !defined (isascii) || defined (STDC_HEADERS)
65 #ifdef isascii
66 #undef isascii
67 #endif
68 #define isascii(c) 1
69 #endif
70
71 #ifdef isblank
72 #define ISBLANK(c) (isascii (c) && isblank (c))
73 #else
74 #define ISBLANK(c) ((c) == ' ' || (c) == '\t')
75 #endif
76
77 #define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \
78                     || (c) == '\f' || (c) == '\v')
79
80 #include <stdio.h>
81 #include <errno.h>
82 #include <getopt.h>
83
84 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
85 #include <string.h>
86 #if !defined(STDC_HEADERS)
87 #include <memory.h>
88 #endif
89 #else
90 #include <strings.h>
91 #define memcpy(dest, source, count) (bcopy((source), (dest), (count)))
92 #endif
93
94 #ifndef _POSIX_SOURCE
95 #include <sys/param.h>
96 #endif
97
98 #ifdef HAVE_LIMITS_H
99 #include <limits.h>
100 #endif
101
102 #ifndef LONG_MAX
103 #define LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
104 #endif
105
106 #ifdef HAVE_UNISTD_H
107 #include <unistd.h>
108 #endif
109
110 #include <signal.h>
111
112 #if !defined(SIGCHLD) && defined(SIGCLD)
113 #define SIGCHLD SIGCLD
114 #endif
115
116 /* COMPAT:  SYSV version defaults size (and has a max value of) to 470.
117    We try to make it as large as possible. */
118 #if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
119 #define ARG_MAX sysconf (_SC_ARG_MAX)
120 #endif
121 #ifndef ARG_MAX
122 #define ARG_MAX NCARGS
123 #endif
124
125 /* States for read_line. */
126 #define NORM 0
127 #define SPACE 1
128 #define QUOTE 2
129 #define BACKSLASH 3
130
131 #ifdef STDC_HEADERS
132 #include <stdlib.h>
133 #else
134 extern int errno;
135 #endif
136
137 /* Return nonzero if S is the EOF string.  */
138 #define EOF_STR(s) (eof_str && *eof_str == *s && !strcmp (eof_str, s))
139
140 extern char **environ;
141
142 /* Not char because of type promotion; NeXT gcc can't handle it.  */
143 typedef int boolean;
144 #define         true    1
145 #define         false   0
146
147 #if __STDC__
148 #define VOID void
149 #else
150 #define VOID char
151 #endif
152
153 VOID *xmalloc P_ ((size_t n));
154 VOID *xrealloc P_ ((VOID * p, size_t n));
155
156 /* The name this program was run with.  */
157 char *program_name;
158
159 /* Buffer for reading arguments from stdin.  */
160 static char *linebuf;
161
162 /* Line number in stdin since the last command was executed.  */
163 static int lineno = 0;
164
165 /* If nonzero, then instead of putting the args from stdin at
166    the end of the command argument list, they are each stuck into the
167    initial args, replacing each occurrence of the `replace_pat' in the
168    initial args.  */
169 static char *replace_pat = NULL;
170
171 /* The length of `replace_pat'.  */
172 static size_t rplen = 0;
173
174 /* If nonzero, when this string is read on stdin it is treated as
175    end of file.
176    I don't like this - it should default to NULL.  */
177 static char *eof_str = "_";
178
179 /* If nonzero, the maximum number of nonblank lines from stdin to use
180    per command line.  */
181 static long lines_per_exec = 0;
182
183 /* The maximum number of arguments to use per command line.  */
184 static long args_per_exec = 1024;
185
186 /* If true, exit if lines_per_exec or args_per_exec is exceeded.  */
187 static boolean exit_if_size_exceeded = false;
188
189 /* The maximum number of characters that can be used per command line.  */
190 static long arg_max;
191
192 /* Storage for elements of `cmd_argv'.  */
193 static char *argbuf;
194
195 /* The list of args being built.  */
196 static char **cmd_argv = NULL;
197
198 /* Number of elements allocated for `cmd_argv'.  */
199 static int cmd_argv_alloc = 0;
200
201 /* Number of valid elements in `cmd_argv'.  */
202 static int cmd_argc = 0;
203
204 /* Number of chars being used in `cmd_argv'.  */
205 static int cmd_argv_chars = 0;
206
207 /* Number of initial arguments given on the command line.  */
208 static int initial_argc = 0;
209
210 /* Number of chars in the initial args.  */
211 static int initial_argv_chars = 0;
212
213 /* true when building up initial arguments in `cmd_argv'.  */
214 static boolean initial_args = true;
215
216 /* If nonzero, the maximum number of child processes that can be running
217    at once.  */
218 static int proc_max = 1;
219
220 /* Total number of child processes that have been executed.  */
221 static int procs_executed = 0;
222
223 /* The number of elements in `pids'.  */
224 static int procs_executing = 0;
225
226 /* List of child processes currently executing.  */
227 static pid_t *pids = NULL;
228
229 /* The number of allocated elements in `pids'. */
230 static int pids_alloc = 0;
231
232 /* Exit status; nonzero if any child process exited with a
233    status of 1-125.  */
234 static int child_error = 0;
235
236 /* If true, print each command on stderr before executing it.  */
237 static boolean print_command = false;
238
239 /* If true, query the user before executing each command, and only
240    execute the command if the user responds affirmatively.  */
241 static boolean query_before_executing = false;
242
243 static struct option const longopts[] =
244 {
245   {"null", no_argument, NULL, '0'},
246   {"eof", optional_argument, NULL, 'e'},
247   {"replace", optional_argument, NULL, 'i'},
248   {"max-lines", optional_argument, NULL, 'l'},
249   {"max-args", required_argument, NULL, 'n'},
250   {"interactive", no_argument, NULL, 'p'},
251   {"no-run-if-empty", no_argument, NULL, 'r'},
252   {"max-chars", required_argument, NULL, 's'},
253   {"verbose", no_argument, NULL, 't'},
254   {"exit", no_argument, NULL, 'x'},
255   {"max-procs", required_argument, NULL, 'P'},
256   {"help", no_argument, NULL, 'h'},
257   {NULL, no_argument, NULL, 0}
258 };
259
260 static int read_line P_ ((void));
261 static int read_string P_ ((void));
262 static void do_insert P_ ((char *arg, size_t arglen, size_t lblen));
263 static void push_arg P_ ((char *arg, size_t len));
264 static boolean print_args P_ ((boolean ask));
265 static void do_exec P_ ((void));
266 static void add_proc P_ ((pid_t pid));
267 static void wait_for_proc P_ ((boolean all));
268 static long parse_num P_ ((char *str, int option, long min, long max));
269 static long env_size P_ ((char **envp));
270
271 int xargs_main (argc, argv)
272      int argc;
273      char **argv;
274 {
275   int optc;
276   int always_run_command = 1;
277   long orig_arg_max;
278   char *default_cmd = "/bin/echo";
279   int (*read_args) P_ ((void)) = read_line;
280
281   program_name = argv[0];
282
283   orig_arg_max = ARG_MAX;
284   if (orig_arg_max == -1)
285     orig_arg_max = LONG_MAX;
286   orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048.  */
287   arg_max = orig_arg_max;
288
289   /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which
290      have it at 1 meg).  Things will work fine with a large ARG_MAX but it
291      will probably hurt the system more than it needs to; an array of this
292      size is allocated.  */
293   if (arg_max > 20 * 1024)
294     arg_max = 20 * 1024;
295
296   /* Take the size of the environment into account.  */
297   arg_max -= env_size (environ);
298   if (arg_max <= 0)
299     fatalError("environment is too large for exec");
300
301   while ((optc = getopt_long (argc, argv, "+0e::i::l::n:prs:txP:",
302                               longopts, (int *) 0)) != -1)
303     {
304       switch (optc)
305         {
306         case '0':
307           read_args = read_string;
308           break;
309
310         case 'e':
311           if (optarg)
312             eof_str = optarg;
313           else
314             eof_str = 0;
315           break;
316
317         case 'h':
318           usage (xargs_usage);
319
320         case 'i':
321           if (optarg)
322             replace_pat = optarg;
323           else
324             replace_pat = "{}";
325           /* -i excludes -n -l.  */
326           args_per_exec = 0;
327           lines_per_exec = 0;
328           break;
329
330         case 'l':
331           if (optarg)
332             lines_per_exec = parse_num (optarg, 'l', 1L, -1L);
333           else
334             lines_per_exec = 1;
335           /* -l excludes -i -n.  */
336           args_per_exec = 0;
337           replace_pat = NULL;
338           break;
339
340         case 'n':
341           args_per_exec = parse_num (optarg, 'n', 1L, -1L);
342           /* -n excludes -i -l.  */
343           lines_per_exec = 0;
344           replace_pat = NULL;
345           break;
346
347         case 's':
348           arg_max = parse_num (optarg, 's', 1L, orig_arg_max);
349           break;
350
351         case 't':
352           print_command = true;
353           break;
354
355         case 'x':
356           exit_if_size_exceeded = true;
357           break;
358
359         case 'p':
360           query_before_executing = true;
361           print_command = true;
362           break;
363
364         case 'r':
365           always_run_command = 0;
366           break;
367
368         case 'P':
369           proc_max = parse_num (optarg, 'P', 0L, -1L);
370           break;
371
372         default:
373           usage (xargs_usage);
374         }
375     }
376
377   if (replace_pat || lines_per_exec)
378     exit_if_size_exceeded = true;
379
380   if (optind == argc)
381     {
382       optind = 0;
383       argc = 1;
384       argv = &default_cmd;
385     }
386
387   linebuf = (char *) xmalloc (arg_max + 1);
388   argbuf = (char *) xmalloc (arg_max + 1);
389
390   /* Make sure to listen for the kids.  */
391   signal (SIGCHLD, SIG_DFL);
392
393   if (!replace_pat)
394     {
395       for (; optind < argc; optind++)
396         push_arg (argv[optind], strlen (argv[optind]) + 1);
397       initial_args = false;
398       initial_argc = cmd_argc;
399       initial_argv_chars = cmd_argv_chars;
400
401       while ((*read_args) () != -1)
402         if (lines_per_exec && lineno >= lines_per_exec)
403           {
404             do_exec ();
405             lineno = 0;
406           }
407
408       /* SYSV xargs seems to do at least one exec, even if the
409          input is empty.  */
410       if (cmd_argc != initial_argc
411           || (always_run_command && procs_executed == 0))
412         do_exec ();
413     }
414   else
415     {
416       int i;
417       size_t len;
418       size_t *arglen = (size_t *) xmalloc (sizeof (size_t) * argc);
419
420       for (i = optind; i < argc; i++)
421         arglen[i] = strlen(argv[i]);
422       rplen = strlen (replace_pat);
423       while ((len = (*read_args) ()) != -1)
424         {
425           /* Don't do insert on the command name.  */
426           push_arg (argv[optind], arglen[optind] + 1);
427           len--;
428           for (i = optind + 1; i < argc; i++)
429             do_insert (argv[i], arglen[i], len);
430           do_exec ();
431         }
432     }
433
434   wait_for_proc (true);
435   exit (child_error);
436 }
437
438 /* Read a line of arguments from stdin and add them to the list of
439    arguments to pass to the command.  Ignore blank lines and initial blanks.
440    Single and double quotes and backslashes quote metacharacters and blanks
441    as they do in the shell.
442    Return -1 if eof (either physical or logical) is reached,
443    otherwise the length of the last string read (including the null).  */
444
445 static int
446 read_line ()
447 {
448   static boolean eof = false;
449   /* Start out in mode SPACE to always strip leading spaces (even with -i).  */
450   int state = SPACE;            /* The type of character we last read.  */
451   int prevc;                    /* The previous value of c.  */
452   int quotc = 0;                /* The last quote character read.  */
453   int c = EOF;
454   boolean first = true;         /* true if reading first arg on line.  */
455   int len;
456   char *p = linebuf;
457   /* Including the NUL, the args must not grow past this point.  */
458   char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
459
460   if (eof)
461     return -1;
462   while (1)
463     {
464       prevc = c;
465       c = getc (stdin);
466       if (c == EOF)
467         {
468           /* COMPAT: SYSV seems to ignore stuff on a line that
469              ends without a \n; we don't.  */
470           eof = true;
471           if (p == linebuf)
472             return -1;
473           *p++ = '\0';
474           len = p - linebuf;
475           /* FIXME we don't check for unterminated quotes here.  */
476           if (first && EOF_STR (linebuf))
477             return -1;
478           if (!replace_pat)
479             push_arg (linebuf, len);
480           return len;
481         }
482       switch (state)
483         {
484         case SPACE:
485           if (ISSPACE (c))
486             continue;
487           state = NORM;
488           /* aaahhhh....  */
489
490         case NORM:
491           if (c == '\n')
492             {
493               if (!ISBLANK (prevc))
494                 lineno++;       /* For -l.  */
495               if (p == linebuf)
496                 {
497                   /* Blank line.  */
498                   state = SPACE;
499                   continue;
500                 }
501               *p++ = '\0';
502               len = p - linebuf;
503               if (EOF_STR (linebuf))
504                 {
505                   eof = true;
506                   return first ? -1 : len;
507                 }
508               if (!replace_pat)
509                 push_arg (linebuf, len);
510               return len;
511             }
512           if (!replace_pat && ISSPACE (c))
513             {
514               *p++ = '\0';
515               len = p - linebuf;
516               if (EOF_STR (linebuf))
517                 {
518                   eof = true;
519                   return first ? -1 : len;
520                 }
521               push_arg (linebuf, len);
522               p = linebuf;
523               state = SPACE;
524               first = false;
525               continue;
526             }
527           switch (c)
528             {
529             case '\\':
530               state = BACKSLASH;
531               continue;
532
533             case '\'':
534             case '"':
535               state = QUOTE;
536               quotc = c;
537               continue;
538             }
539           break;
540
541         case QUOTE:
542           if (c == '\n')
543             fatalError ("unmatched %s quote", quotc == '"' ? "double" : "single");
544           if (c == quotc)
545             {
546               state = NORM;
547               continue;
548             }
549           break;
550
551         case BACKSLASH:
552           state = NORM;
553           break;
554         }
555       if (p >= endbuf)
556         fatalError ("argument line too long");
557       *p++ = c;
558     }
559 }
560
561 /* Read a null-terminated string from stdin and add it to the list of
562    arguments to pass to the command.
563    Return -1 if eof (either physical or logical) is reached,
564    otherwise the length of the string read (including the null).  */
565
566 static int
567 read_string ()
568 {
569   static boolean eof = false;
570   int len;
571   char *p = linebuf;
572   /* Including the NUL, the args must not grow past this point.  */
573   char *endbuf = linebuf + arg_max - initial_argv_chars - 1;
574
575   if (eof)
576     return -1;
577   while (1)
578     {
579       int c = getc (stdin);
580       if (c == EOF)
581         {
582           eof = true;
583           if (p == linebuf)
584             return -1;
585           *p++ = '\0';
586           len = p - linebuf;
587           if (!replace_pat)
588             push_arg (linebuf, len);
589           return len;
590         }
591       if (c == '\0')
592         {
593           lineno++;             /* For -l.  */
594           *p++ = '\0';
595           len = p - linebuf;
596           if (!replace_pat)
597             push_arg (linebuf, len);
598           return len;
599         }
600       if (p >= endbuf)
601         fatalError ("argument line too long");
602       *p++ = c;
603     }
604 }
605
606 /* Replace all instances of `replace_pat' in ARG with `linebuf',
607    and add the resulting string to the list of arguments for the command
608    to execute.
609    ARGLEN is the length of ARG, not including the null.
610    LBLEN is the length of `linebuf', not including the null.
611
612    COMPAT: insertions on the SYSV version are limited to 255 chars per line,
613    and a max of 5 occurences of replace_pat in the initial-arguments.
614    Those restrictions do not exist here.  */
615
616 static void
617 do_insert (arg, arglen, lblen)
618      char *arg;
619      size_t arglen;
620      size_t lblen;
621 {
622   /* Temporary copy of each arg with the replace pattern replaced by the
623      real arg.  */
624   static char *insertbuf;
625   char *p;
626   int bytes_left = arg_max - 1; /* Bytes left on the command line.  */
627
628   if (!insertbuf)
629     insertbuf = (char *) xmalloc (arg_max + 1);
630   p = insertbuf;
631
632   do
633     {
634       size_t len;               /* Length in ARG before `replace_pat'.  */
635       char *s = strstr (arg, replace_pat);
636       if (s)
637         len = s - arg;
638       else
639         len = arglen;
640       bytes_left -= len;
641       if (bytes_left <= 0)
642         break;
643
644       strncpy (p, arg, len);
645       p += len;
646       arg += len;
647       arglen -= len;
648
649       if (s)
650         {
651           bytes_left -= lblen;
652           if (bytes_left <= 0)
653             break;
654           strcpy (p, linebuf);
655           arg += rplen;
656           arglen -= rplen;
657           p += lblen;
658         }
659     }
660   while (*arg);
661   if (*arg)
662     fatalError ("command too long");
663   *p++ = '\0';
664   push_arg (insertbuf, p - insertbuf);
665 }
666
667 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
668    to the command.
669    LEN is the length of ARG, including the terminating null.
670    If this brings the list up to its maximum size, execute the command.  */
671
672 static void
673 push_arg (arg, len)
674      char *arg;
675      size_t len;
676 {
677   if (arg)
678     {
679       if (cmd_argv_chars + len > arg_max)
680         {
681           if (initial_args || cmd_argc == initial_argc)
682             fatalError ("can not fit single argument within argument list size limit");
683           if (replace_pat
684               || (exit_if_size_exceeded &&
685                   (lines_per_exec || args_per_exec)))
686             fatalError ("argument list too long");
687           do_exec ();
688         }
689       if (!initial_args && args_per_exec &&
690           cmd_argc - initial_argc == args_per_exec)
691         do_exec ();
692     }
693
694   if (cmd_argc >= cmd_argv_alloc)
695     {
696       if (!cmd_argv)
697         {
698           cmd_argv_alloc = 64;
699           cmd_argv = (char **) xmalloc (sizeof (char *) * cmd_argv_alloc);
700         }
701       else
702         {
703           cmd_argv_alloc *= 2;
704           cmd_argv = (char **) xrealloc (cmd_argv,
705                                          sizeof (char *) * cmd_argv_alloc);
706         }
707     }
708
709   if (!arg)
710     cmd_argv[cmd_argc++] = NULL;
711   else
712     {
713       cmd_argv[cmd_argc++] = argbuf + cmd_argv_chars;
714       strcpy (argbuf + cmd_argv_chars, arg);
715       cmd_argv_chars += len;
716     }
717 }
718
719 /* Print the arguments of the command to execute.
720    If ASK is nonzero, prompt the user for a response, and
721    if the user responds affirmatively, return true;
722    otherwise, return false.  */
723
724 static boolean
725 print_args (ask)
726      boolean ask;
727 {
728   int i;
729
730   for (i = 0; i < cmd_argc - 1; i++)
731     fprintf (stderr, "%s ", cmd_argv[i]);
732   if (ask)
733     {
734       static FILE *tty_stream;
735       int c, savec;
736
737       if (!tty_stream)
738         {
739           tty_stream = fopen ("/dev/tty", "r");
740           if (!tty_stream)
741             fatalError (" Could not open /dev/tty");
742         }
743       fputs ("?...", stderr);
744       fflush (stderr);
745       c = savec = getc (tty_stream);
746       while (c != EOF && c != '\n')
747         c = getc (tty_stream);
748       if (savec == 'y' || savec == 'Y')
749         return true;
750     }
751   else
752     putc ('\n', stderr);
753
754   return false;
755 }
756
757 /* Execute the command that has been built in `cmd_argv'.  This may involve
758    waiting for processes that were previously executed.  */
759
760 static void
761 do_exec ()
762 {
763   pid_t child;
764
765   push_arg ((char *) NULL, 0);  /* Null terminate the arg list.  */
766   if (!query_before_executing || print_args (true))
767     {
768       if (proc_max && procs_executing >= proc_max)
769         wait_for_proc (false);
770       if (!query_before_executing && print_command)
771         print_args (false);
772       /* If we run out of processes, wait for a child to return and
773          try again.  */
774       while ((child = fork ()) < 0 && errno == EAGAIN && procs_executing)
775         wait_for_proc (false);
776       switch (child)
777         {
778         case -1:
779           fatalError ("cannot fork");
780
781         case 0:         /* Child.  */
782           execvp (cmd_argv[0], cmd_argv);
783           errorMsg ("failed to exec '%s'", cmd_argv[0]);
784           _exit (errno == ENOENT ? 127 : 126);
785         }
786       add_proc (child);
787     }
788
789   cmd_argc = initial_argc;
790   cmd_argv_chars = initial_argv_chars;
791 }
792
793 /* Add the process with id PID to the list of processes that have
794    been executed.  */
795
796 static void
797 add_proc (pid)
798      pid_t pid;
799 {
800   int i;
801
802   /* Find an empty slot.  */
803   for (i = 0; i < pids_alloc && pids[i]; i++)
804     ;
805   if (i == pids_alloc)
806     {
807       if (pids_alloc == 0)
808         {
809           pids_alloc = proc_max ? proc_max : 64;
810           pids = (pid_t *) xmalloc (sizeof (pid_t) * pids_alloc);
811         }
812       else
813         {
814           pids_alloc *= 2;
815           pids = (pid_t *) xrealloc (pids,
816                                      sizeof (pid_t) * pids_alloc);
817         }
818       memset (&pids[i], '\0', sizeof (pid_t) * (pids_alloc - i));
819     }
820   pids[i] = pid;
821   procs_executing++;
822   procs_executed++;
823 }
824
825 /* If ALL is true, wait for all child processes to finish;
826    otherwise, wait for one child process to finish.
827    Remove the processes that finish from the list of executing processes.  */
828
829 static void
830 wait_for_proc (all)
831      boolean all;
832 {
833   while (procs_executing)
834     {
835       int i, status;
836
837       do
838         {
839           pid_t pid;
840
841           pid = wait (&status);
842           if (pid < 0)
843             fatalError ("error waiting for child process");
844
845           /* Find the entry in `pids' for the child process
846              that exited.  */
847           for (i = 0; i < pids_alloc && pid != pids[i]; i++)
848             ;
849         }
850       while (i == pids_alloc);  /* A child died that we didn't start? */
851
852       /* Remove the child from the list.  */
853       pids[i] = 0;
854       procs_executing--;
855
856       if (WEXITSTATUS (status) == 126 || WEXITSTATUS (status) == 127)
857         exit (WEXITSTATUS (status));    /* Can't find or run the command.  */
858       if (WEXITSTATUS (status) == 255)
859         fatalError ( "%s: exited with status 255; aborting", cmd_argv[0]);
860       if (WIFSTOPPED (status))
861         fatalError ( "%s: stopped by signal %d", cmd_argv[0], WSTOPSIG (status));
862       if (WIFSIGNALED (status))
863         fatalError ("%s: terminated by signal %d", cmd_argv[0], WTERMSIG (status));
864       if (WEXITSTATUS (status) != 0)
865         child_error = 123;
866
867       if (!all)
868         break;
869     }
870 }
871
872 /* Return the value of the number represented in STR.
873    OPTION is the command line option to which STR is the argument.
874    If the value does not fall within the boundaries MIN and MAX,
875    Print an error message mentioning OPTION and exit.  */
876
877 static long
878 parse_num (str, option, min, max)
879      char *str;
880      int option;
881      long min;
882      long max;
883 {
884   char *eptr;
885   long val;
886
887   val = strtol (str, &eptr, 10);
888   if (eptr == str || *eptr)
889     {
890       fprintf (stderr, "%s: invalid number for -%c option\n",
891                program_name, option);
892       usage (xargs_usage);
893     }
894   else if (val < min)
895     {
896       fprintf (stderr, "%s: value for -%c option must be >= %ld\n",
897                program_name, option, min);
898       usage (xargs_usage);
899     }
900   else if (max >= 0 && val > max)
901     {
902       fprintf (stderr, "%s: value for -%c option must be < %ld\n",
903                program_name, option, max);
904       usage (xargs_usage);
905     }
906   return val;
907 }
908
909 /* Return how much of ARG_MAX is used by the environment.  */
910
911 static long
912 env_size (envp)
913      char **envp;
914 {
915   long len = 0;
916
917   while (*envp)
918     len += strlen (*envp++) + 1;
919
920   return len;
921 }
922