last_patch95 from vodz:
[oweals/busybox.git] / findutils / xargs.c
index 478e0ee6d630549a3f1727c8de3c240b1a77da1f..2b18f8f28fd5f31d2caba41224129afa90ea0c52 100644 (file)
@@ -1,9 +1,10 @@
-/* vi: set sw=4 ts=4: */
 /*
  * Mini xargs implementation for busybox
+ * Only "-prt" options are supported in this version of xargs.
  *
- * Copyright (C) 2000 by Lineo, inc.
- * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
+ * (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru>
+ *
+ * Special thanks Mark Whitley for stimul to rewrote :)
  *
  * 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 <stdio.h>
-#include <string.h>
-#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
 #include <getopt.h>
-#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "busybox.h"
 
 
-int xargs_main(int argc, char **argv)
+/*
+   This function have special algorithm.
+   Don`t use fork and include to main!
+*/
+static void xargs_exec(char * const * args)
 {
-       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) */
-       if (argc == 1) {
-               len_args_from_cmdline = 6;
-               args_from_cmdline = xmalloc(len_args_from_cmdline);
-               strcat(args_from_cmdline, "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);
+       int p;
+       int common[4];  /* shared vfork stack */
+
+       common[0] = 0;
+       if ((p = vfork()) >= 0) {
+               if (p == 0) {
+                       /* vfork -- child */
+                       execvp(args[0], args);
+                       common[0] = errno; /* set error to shared stack */
+                       _exit(1);
+               } else {
+                       /* vfork -- parent */
+                       wait(NULL);
+                       if(common[0]) {
+                               errno = common[0];
+                               bb_perror_msg_and_die("%s", args[0]);
                        }
-                       strcat(args_from_cmdline, *argv);
-                       strcat(args_from_cmdline, " ");
                }
+       } else {
+               bb_perror_msg_and_die("vfork");
        }
+}
 
-       /* 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));
+int xargs_main(int argc, char **argv)
+{
+       char *file_to_act_on;
+       char **args;
+       int  i, a;
+       char flg_vi;            /* verbose |& interactive */
+       char flg_no_empty;
+
+       bb_opt_complementaly = "pt";
+       a = bb_getopt_ulflags(argc, argv, "tpr");
+       flg_vi = a & 3;
+       flg_no_empty = a & 4;
+
+       a = argc - optind;
+       argv += optind;
+       if(a==0) {
+               /* default behavior is to echo all the filenames */
+               *argv = "/bin/echo";
+               a++;
+       }
+       /* allocating pointers for execvp: a*arg, arg from stdin, NULL */
+       args = xcalloc(a + 3, sizeof(char *));
+
+       /* Store the command to be executed (taken from the command line) */
+       for (i = 0; i < a; i++)
+               args[i] = *argv++;
+
+       /* 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 = bb_get_chomped_line_from_file(stdin)) != NULL) {
+               if(file_to_act_on[0] != 0 || flg_no_empty == 0) {
+                       args[a] = file_to_act_on[0] ? file_to_act_on : NULL;
+                       if(flg_vi) {
+                               for(i=0; args[i]; i++) {
+                                       if(i)
+                                               fputc(' ', stderr);
+                                       fputs(args[i], stderr);
+                               }
+                               fputs(((flg_vi & 2) ? " ?..." : "\n"), stderr);
+                       }
+                       if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) {
+                               xargs_exec(args);
+                       }
                }
-
-               /* 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 */
+               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);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+       free(args);
 #endif
-
        return 0;
 }
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/
-