-/* minix xargs - Make and execute commands
- * Author: Ian Nicholls: 1 Mar 90 */
-
/*
- * xargs - Accept words from stdin until, combined with the arguments
- * given on the command line, just fit into the command line limit.
- * Then, execute the result.
- * e.g. ls | xargs compress
- * find . -name '*.s' -print | xargs ar qv libc.a
+ * Mini xargs implementation for busybox
+ *
+ * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
+ * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
+ * Remixed by Mark Whitley <markw@codepoet.org>
*
- * flags: -t Print the command just before it is run
- * -l len Use len as maximum line length (default 490, max 1023)
- * -e ending Append ending to the command before executing it.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * Exits with: 0 No errors.
- * 1 If any system(3) call returns a nonzero status.
- * 2 Usage error
- * 3 Line length too short to contain some single argument.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
- * Examples: xargs ar qv libc.a < liborder # Create a new libc.a
- * find . -name '*.s' -print | xargs rm # Remove all .s files
- * find . -type f ! -name '*.Z' \ # Compress old files.
- * -atime +60 -print | xargs compress -v
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Bugs: If the command contains unquoted wildflags, then the system(3) call
- * call may expand this to larger than the maximum line size.
- * The command is not executed if nothing was read from stdin.
- * xargs may give up too easily when the command returns nonzero.
*/
-#define USAGE "usage: xargs [-t] [-l len] [-e endargs] command [args...]\n"
-#include <errno.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
-#include <getopt.h>
+#include "busybox.h"
-#ifndef MAX_ARGLINE
-# define MAX_ARGLINE 1023
-#endif
-#ifndef min
-# define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
+int xargs_main(int argc, char **argv)
+{
+ char *cmd_to_be_executed;
+ char *file_to_act_on;
+ int i;
+ int len;
-char outlin[MAX_ARGLINE];
-char inlin[MAX_ARGLINE];
-char startlin[MAX_ARGLINE];
-char *ending = NULL;
-char traceflag = 0;
+ /*
+ * No options are supported in this version of xargs; no getopt.
+ *
+ * Re: The missing -t flag: Most programs that produce output also print
+ * the filename, so xargs doesn't really need to do it again. Supporting
+ * the -t flag =greatly= bloats up the size of this app and the memory it
+ * uses because you have to buffer all the input file strings in memory. If
+ * you really want to see the filenames that xargs will act on, just run it
+ * once with no args and xargs will echo the filename. Simple.
+ */
-int xargs_main(int ac, char **av)
-{
- int outlen, inlen, startlen, endlen=0, i;
- char errflg = 0;
- int maxlin = MAX_ARGLINE;
+ argv++;
+ len = argc; /* arg = count for ' ' + trailing '\0' */
+ /* Store the command to be executed (taken from the command line) */
+ if (argc == 1) {
+ /* default behavior is to echo all the filenames */
+ argv[0] = "/bin/echo";
+ len++; /* space for trailing '\0' */
+ } else {
+ argc--;
+ }
+ /* concatenate all the arguments passed to xargs together */
+ for (i = 0; i < argc; i++)
+ len += strlen(argv[i]);
+ cmd_to_be_executed = xmalloc (len);
+ for (i = len = 0; i < argc; i++) {
+ len = sprintf(cmd_to_be_executed + len, "%s ", argv[i]);
+ }
- while ((i = getopt(ac, av, "tl:e:")) != EOF)
- switch (i) {
- case 't': traceflag = 1; break;
- case 'l': maxlin = min(MAX_ARGLINE, atoi(optarg)); break;
- case 'e': ending = optarg; break;
- case '?': errflg++; break;
- }
- if (errflg) {
- fprintf(stderr, USAGE);
- exit(2);
- }
+ /* Now, read in one line at a time from stdin, and store this
+ * line to be used later as an argument to the command */
+ while ((file_to_act_on = get_line_from_file(stdin)) !=NULL) {
- startlin[0] = 0;
- if (optind == ac) {
- strcat(startlin, "echo ");
- }
- else for ( ; optind < ac; optind++) {
- strcat(startlin, av[optind]);
- strcat(startlin, " ");
- }
- startlen = strlen(startlin);
- if (ending) endlen = strlen(ending);
- maxlin = maxlin - 1 - endlen; /* Pre-compute */
+ FILE *cmd_output;
+ char *output_line;
+ char *execstr;
- strcpy(outlin, startlin);
- outlen = startlen;
+ /* eat the newline off the filename. */
+ chomp(file_to_act_on);
- while (gets(inlin) != NULL) {
- inlen = strlen(inlin);
- if (maxlin <= (outlen + inlen)) {
- if (outlen == startlen) {
- fprintf(stderr, "%s: Line length too short to process '%s'\n",
- av[0], inlin);
- exit(3);
- }
- if (ending) strcat(outlin, ending);
- if (traceflag) fputs(outlin,stderr);
- errno = 0;
- if (0 != system(outlin)) {
- if (errno != 0) perror("xargs");
- exit(1);
- }
- strcpy(outlin, startlin);
- outlen = startlen;
- }
- strcat(outlin, inlin);
- strcat(outlin, " ");
- outlen = outlen + inlen + 1;
- }
- if (outlen != startlen) {
- if (ending) strcat(outlin, ending);
- if (traceflag) fputs(outlin,stderr);
- errno = 0;
- if (0 != system(outlin)) {
- if (errno != 0) perror("xargs");
- exit(1);
- }
- }
- return 0;
+ /* eat blank lines */
+ if (file_to_act_on[0] == 0)
+ continue;
+
+ /* assemble the command and execute it */
+ bb_asprintf(&execstr, "%s%s", cmd_to_be_executed, file_to_act_on);
+
+ cmd_output = popen(execstr, "r");
+ if (cmd_output == NULL)
+ perror_msg_and_die("popen");
+
+ /* harvest the output */
+ while ((output_line = get_line_from_file(cmd_output)) != NULL) {
+ fputs(output_line, stdout);
+ free(output_line);
+ }
+
+ /* clean up */
+ pclose(cmd_output);
+ free(execstr);
+ free(file_to_act_on);
+ }
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+ free(cmd_to_be_executed);
+#endif
+
+ return 0;
}
+
+/* vi: set sw=4 ts=4: */