Regression testing bugfixes from Larry Doolittle. As an aside,
[oweals/busybox.git] / xargs.c
diff --git a/xargs.c b/xargs.c
index 478e0ee6d630549a3f1727c8de3c240b1a77da1f..f05efd917263be560823a27ae217c7e8060950ff 100644 (file)
--- a/xargs.c
+++ b/xargs.c
@@ -1,9 +1,9 @@
-/* vi: set sw=4 ts=4: */
 /*
  * Mini xargs implementation for busybox
  *
- * Copyright (C) 2000 by Lineo, inc.
+ * Copyright (C) 1999,2000,2001 by Lineo, inc.
  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
+ * Remixed by Mark Whitley <markw@lineo.com>, <markw@codepoet.org>
  *
  * 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
  *
  */
 
-#include "internal.h"
-#include <stdlib.h>
+#include "busybox.h"
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <getopt.h>
-#include <ctype.h>
-
 
 int xargs_main(int argc, char **argv)
 {
-       char *in_from_stdin = NULL;
-       char *args_from_cmdline = NULL;
        char *cmd_to_be_executed = NULL;
-       char traceflag = 0;
-       int len_args_from_cmdline, len_cmd_to_be_executed, len, opt;
-
-       /* Note that we do not use getopt here, since
-        * we only want to interpret initial options,
-        * not options passed to commands */
-       while (--argc && **(++argv) == '-') {
-               while (*++(*argv)) {
-                       switch (**argv) {
-                               case 't':
-                                       traceflag=1;
-                                       break;
-                               default:
-                                       fatalError(xargs_usage);
-                               }
-               }
-       }
-
-       /* Store the command and arguments to be executed (from the command line) */
+       char *file_to_act_on = NULL;
+
+       /*
+        * 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.
+        */
+
+       /* Store the command to be executed (taken from the command line) */
        if (argc == 1) {
-               len_args_from_cmdline = 6;
-               args_from_cmdline = xmalloc(len_args_from_cmdline);
-               strcat(args_from_cmdline, "echo ");
+               /* default behavior is to echo all the filenames */
+               cmd_to_be_executed = strdup("/bin/echo ");
        } else {
-               opt=strlen(*argv);
-               len_args_from_cmdline = (opt > 10)? opt : 10;
-               args_from_cmdline = xcalloc(len_args_from_cmdline, sizeof(char));
-               while (argc-- > 0) {
-                       if (strlen(*argv) + strlen(args_from_cmdline) >
-                               len_args_from_cmdline) {
-                               len_args_from_cmdline += strlen(*argv);
-                               args_from_cmdline =
-                                       xrealloc(args_from_cmdline,
-                                                        len_args_from_cmdline+1);
-                       }
-                       strcat(args_from_cmdline, *argv);
-                       strcat(args_from_cmdline, " ");
+               /* concatenate all the arguments passed to xargs together */
+               int i;
+               int len = 1; /* for the '\0' */
+               for (i = 1; i < argc; i++) {
+                       len += strlen(argv[i]);
+                       len += 1;  /* for the space between the args */
+                       cmd_to_be_executed = xrealloc(cmd_to_be_executed, len);
+                       strcat(cmd_to_be_executed, argv[i]);
+                       strcat(cmd_to_be_executed, " ");
                }
        }
 
-       /* Set up some space for the command to be executed to be held in */
-       len_cmd_to_be_executed=10;
-       cmd_to_be_executed = xcalloc(len_cmd_to_be_executed, sizeof(char));
-       strcpy(cmd_to_be_executed, args_from_cmdline);
-       strcat(cmd_to_be_executed, " \"");
-
-       /* Now, read in one line at a time from stdin, and run command+args on it */
-       in_from_stdin = get_line_from_file(stdin);
-       for (;in_from_stdin!=NULL;) {
-               char *tmp;
-               opt = strlen(in_from_stdin);
-               len = opt + len_args_from_cmdline;
-               len_cmd_to_be_executed+=len+3;
-               cmd_to_be_executed=xrealloc(cmd_to_be_executed, len_cmd_to_be_executed);
-                       
-               /* Strip out the final \n */
-               in_from_stdin[opt-1]=' ';
-               
-               /* Replace any tabs with spaces */
-               while( (tmp = strchr(in_from_stdin, '\t')) != NULL )
-                       *tmp=' ';
-
-               /* Strip out any extra intra-word spaces */
-               while( (tmp = strstr(in_from_stdin, "  ")) != NULL ) {
-                       opt = strlen(in_from_stdin);
-                       memmove(tmp, tmp+1, opt-(tmp-in_from_stdin));
+       /* 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) {
+
+               FILE *cmd_output = NULL;
+               char *output_line = NULL;
+               char *execstr = NULL;
+
+               /* eat the newline off the filename. */
+               chomp(file_to_act_on);
+
+               /* eat blank lines */
+               if (strlen(file_to_act_on) == 0)
+                       continue;
+
+               /* assemble the command and execute it */
+               execstr = xcalloc(strlen(cmd_to_be_executed) +
+                               strlen(file_to_act_on) + 1, sizeof(char));
+               strcat(execstr, cmd_to_be_executed);
+               strcat(execstr, 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);
                }
 
-               /* trim trailing whitespace */
-               opt = strlen(in_from_stdin) - 1;
-               while (isspace(in_from_stdin[opt]))
-                       opt--;
-               in_from_stdin[++opt] = 0;
-
-               /* Strip out any leading whitespace */
-               tmp=in_from_stdin;
-               while(isspace(*tmp))
-                       tmp++;
-
-               strcat(cmd_to_be_executed, tmp);
-               strcat(cmd_to_be_executed, " ");
-       
-               free(in_from_stdin);
-               in_from_stdin = get_line_from_file(stdin);
+               /* clean up */
+               pclose(cmd_output);
+               free(execstr);
+               free(file_to_act_on);
        }
 
-       strcat(cmd_to_be_executed, "\"");
-       if (traceflag==1)
-               fputs(cmd_to_be_executed, stderr);
-
-       if ((system(cmd_to_be_executed) != 0) && (errno != 0))
-               fatalError("%s", strerror(errno));
-
-
 #ifdef BB_FEATURE_CLEAN_UP
-       free(args_from_cmdline);
        free(cmd_to_be_executed);
 #endif
 
        return 0;
 }
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
 
+/* vi: set sw=4 ts=4: */