-#else
-extern int errno;
-#endif
-
-/* Return nonzero if S is the EOF string. */
-#define EOF_STR(s) (eof_str && *eof_str == *s && !strcmp (eof_str, s))
-
-extern char **environ;
-
-/* Not char because of type promotion; NeXT gcc can't handle it. */
-typedef int boolean;
-#define true 1
-#define false 0
-
-#if __STDC__
-#define VOID void
-#else
-#define VOID char
-#endif
-
-VOID *xmalloc P_ ((size_t n));
-VOID *xrealloc P_ ((VOID * p, size_t n));
-
-/* The name this program was run with. */
-char *program_name;
-
-/* Buffer for reading arguments from stdin. */
-static char *linebuf;
-
-/* Line number in stdin since the last command was executed. */
-static int lineno = 0;
-
-/* If nonzero, then instead of putting the args from stdin at
- the end of the command argument list, they are each stuck into the
- initial args, replacing each occurrence of the `replace_pat' in the
- initial args. */
-static char *replace_pat = NULL;
-
-/* The length of `replace_pat'. */
-static size_t rplen = 0;
-
-/* If nonzero, when this string is read on stdin it is treated as
- end of file.
- I don't like this - it should default to NULL. */
-static char *eof_str = "_";
-
-/* If nonzero, the maximum number of nonblank lines from stdin to use
- per command line. */
-static long lines_per_exec = 0;
-
-/* The maximum number of arguments to use per command line. */
-static long args_per_exec = 1024;
-
-/* If true, exit if lines_per_exec or args_per_exec is exceeded. */
-static boolean exit_if_size_exceeded = false;
-
-/* The maximum number of characters that can be used per command line. */
-static long arg_max;
-
-/* Storage for elements of `cmd_argv'. */
-static char *argbuf;
-
-/* The list of args being built. */
-static char **cmd_argv = NULL;
-
-/* Number of elements allocated for `cmd_argv'. */
-static int cmd_argv_alloc = 0;
-
-/* Number of valid elements in `cmd_argv'. */
-static int cmd_argc = 0;
-
-/* Number of chars being used in `cmd_argv'. */
-static int cmd_argv_chars = 0;
-
-/* Number of initial arguments given on the command line. */
-static int initial_argc = 0;
-
-/* Number of chars in the initial args. */
-static int initial_argv_chars = 0;
-
-/* true when building up initial arguments in `cmd_argv'. */
-static boolean initial_args = true;
-
-/* If nonzero, the maximum number of child processes that can be running
- at once. */
-static int proc_max = 1;
-
-/* Total number of child processes that have been executed. */
-static int procs_executed = 0;
-
-/* The number of elements in `pids'. */
-static int procs_executing = 0;
-
-/* List of child processes currently executing. */
-static pid_t *pids = NULL;
-
-/* The number of allocated elements in `pids'. */
-static int pids_alloc = 0;
-
-/* Exit status; nonzero if any child process exited with a
- status of 1-125. */
-static int child_error = 0;
-
-/* If true, print each command on stderr before executing it. */
-static boolean print_command = false;
-
-/* If true, query the user before executing each command, and only
- execute the command if the user responds affirmatively. */
-static boolean query_before_executing = false;
-
-static struct option const longopts[] =
-{
- {"null", no_argument, NULL, '0'},
- {"eof", optional_argument, NULL, 'e'},
- {"replace", optional_argument, NULL, 'i'},
- {"max-lines", optional_argument, NULL, 'l'},
- {"max-args", required_argument, NULL, 'n'},
- {"interactive", no_argument, NULL, 'p'},
- {"no-run-if-empty", no_argument, NULL, 'r'},
- {"max-chars", required_argument, NULL, 's'},
- {"verbose", no_argument, NULL, 't'},
- {"exit", no_argument, NULL, 'x'},
- {"max-procs", required_argument, NULL, 'P'},
- {"help", no_argument, NULL, 'h'},
- {NULL, no_argument, NULL, 0}
-};
-
-static int read_line P_ ((void));
-static int read_string P_ ((void));
-static void do_insert P_ ((char *arg, size_t arglen, size_t lblen));
-static void push_arg P_ ((char *arg, size_t len));
-static boolean print_args P_ ((boolean ask));
-static void do_exec P_ ((void));
-static void add_proc P_ ((pid_t pid));
-static void wait_for_proc P_ ((boolean all));
-static long parse_num P_ ((char *str, int option, long min, long max));
-static long env_size P_ ((char **envp));
-
-int xargs_main (argc, argv)
- int argc;
- char **argv;
-{
- int optc;
- int always_run_command = 1;
- long orig_arg_max;
- char *default_cmd = "/bin/echo";
- int (*read_args) P_ ((void)) = read_line;
-
- program_name = argv[0];
-
- orig_arg_max = ARG_MAX;
- if (orig_arg_max == -1)
- orig_arg_max = LONG_MAX;
- orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048. */
- arg_max = orig_arg_max;
-
- /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which
- have it at 1 meg). Things will work fine with a large ARG_MAX but it
- will probably hurt the system more than it needs to; an array of this
- size is allocated. */
- if (arg_max > 20 * 1024)
- arg_max = 20 * 1024;
-
- /* Take the size of the environment into account. */
- arg_max -= env_size (environ);
- if (arg_max <= 0)
- fatalError("environment is too large for exec");
-
- while ((optc = getopt_long (argc, argv, "+0e::i::l::n:prs:txP:",
- longopts, (int *) 0)) != -1)
- {
- switch (optc)
- {
- case '0':
- read_args = read_string;
- break;
-
- case 'e':
- if (optarg)
- eof_str = optarg;
- else
- eof_str = 0;
- break;
-
- case 'h':
- usage (xargs_usage);
-
- case 'i':
- if (optarg)
- replace_pat = optarg;
- else
- replace_pat = "{}";
- /* -i excludes -n -l. */
- args_per_exec = 0;
- lines_per_exec = 0;
- break;
-
- case 'l':
- if (optarg)
- lines_per_exec = parse_num (optarg, 'l', 1L, -1L);
- else
- lines_per_exec = 1;
- /* -l excludes -i -n. */
- args_per_exec = 0;
- replace_pat = NULL;
- break;
-
- case 'n':
- args_per_exec = parse_num (optarg, 'n', 1L, -1L);
- /* -n excludes -i -l. */
- lines_per_exec = 0;
- replace_pat = NULL;
- break;
-
- case 's':
- arg_max = parse_num (optarg, 's', 1L, orig_arg_max);
- break;
-
- case 't':
- print_command = true;
- break;
-
- case 'x':
- exit_if_size_exceeded = true;
- break;
-
- case 'p':
- query_before_executing = true;
- print_command = true;
- break;
-
- case 'r':
- always_run_command = 0;
- break;
-
- case 'P':
- proc_max = parse_num (optarg, 'P', 0L, -1L);
- break;
-
- default:
- usage (xargs_usage);
- }
- }
-
- if (replace_pat || lines_per_exec)
- exit_if_size_exceeded = true;
-
- if (optind == argc)
- {
- optind = 0;
- argc = 1;
- argv = &default_cmd;
- }
-
- linebuf = (char *) xmalloc (arg_max + 1);
- argbuf = (char *) xmalloc (arg_max + 1);
-
- /* Make sure to listen for the kids. */
- signal (SIGCHLD, SIG_DFL);
-
- if (!replace_pat)
- {
- for (; optind < argc; optind++)
- push_arg (argv[optind], strlen (argv[optind]) + 1);
- initial_args = false;
- initial_argc = cmd_argc;
- initial_argv_chars = cmd_argv_chars;
-
- while ((*read_args) () != -1)
- if (lines_per_exec && lineno >= lines_per_exec)
- {
- do_exec ();
- lineno = 0;
- }
-
- /* SYSV xargs seems to do at least one exec, even if the
- input is empty. */
- if (cmd_argc != initial_argc
- || (always_run_command && procs_executed == 0))
- do_exec ();
- }
- else
- {
- int i;
- size_t len;
- size_t *arglen = (size_t *) xmalloc (sizeof (size_t) * argc);
-
- for (i = optind; i < argc; i++)
- arglen[i] = strlen(argv[i]);
- rplen = strlen (replace_pat);
- while ((len = (*read_args) ()) != -1)
- {
- /* Don't do insert on the command name. */
- push_arg (argv[optind], arglen[optind] + 1);
- len--;
- for (i = optind + 1; i < argc; i++)
- do_insert (argv[i], arglen[i], len);
- do_exec ();
- }
- }
-
- wait_for_proc (true);
- exit (child_error);
-}
-
-/* Read a line of arguments from stdin and add them to the list of
- arguments to pass to the command. Ignore blank lines and initial blanks.
- Single and double quotes and backslashes quote metacharacters and blanks
- as they do in the shell.
- Return -1 if eof (either physical or logical) is reached,
- otherwise the length of the last string read (including the null). */