last_patch95 from vodz:
[oweals/busybox.git] / findutils / xargs.c
index 21bfb6bbee5ca6e0b3da66118cdebeb36801b533..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>
-
-/* get_sh_safe_line_from_file() - This function reads an entire line from a text file
- * up to a newline. It returns a malloc'ed char * which must be stored and
- * free'ed  by the caller. */
-extern char *get_sh_safe_line_from_file(FILE *file)
-{
-       static const int GROWBY = 80; /* how large we will grow strings by */
-
-       char ch, last_ch = 0;
-       char tmp[]=" ";
-       int idx = 0;
-       char *linebuf = NULL;
-       int linebufsz = 0;
-
-       while (1) {
-               ch = fgetc(file);
-               if (ch == EOF)
-                       break;
-               
-               /* grow the line buffer as necessary */
-               while (idx > linebufsz-4)
-                       linebuf = xrealloc(linebuf, linebufsz += GROWBY);
-
-               /* Remove any extra spaces */
-               if (last_ch == ' ' && ch == ' ')
-                       continue;
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "busybox.h"
 
-               /* Replace any tabs with spaces */
-               if (ch == '\t')
-                       ch=' ';
 
-               /* Escape any characters that are treated specially by /bin/sh */
-               *tmp=ch;
-               if (strpbrk(tmp, "\\~`!$^&*()=|{}[];\"'<>?#") != NULL && last_ch!='\\') {
-                       linebuf[idx++] = '\\';
+/*
+   This function have special algorithm.
+   Don`t use fork and include to main!
+*/
+static void xargs_exec(char * const * args)
+{
+       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]);
+                       }
                }
-
-               linebuf[idx++] = ch;
-               last_ch=ch;
-
-               if (ch == '\n')
-                       break;
+       } else {
+               bb_perror_msg_and_die("vfork");
        }
-       if (idx == 0 && last_ch!=0)
-               linebuf[idx++]=' ';
-
-       if (idx == 0)
-               return NULL;
-
-       linebuf[idx] = 0;
-       return linebuf;
 }
 
-
-
 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);
-                               }
-               }
+       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++;
        }
-
-       /* Store the command and arguments to be executed (from the command line) */
-       if (argc == 0) {
-               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);
+       /* 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);
                        }
-                       strcat(args_from_cmdline, *argv);
-                       strcat(args_from_cmdline, " ");
-                       ++argv;
                }
+               /* clean up */
+               free(file_to_act_on);
        }
-
-       /* 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);
-
-       /* Now, read in one line at a time from stdin, and run command+args on it */
-       in_from_stdin = get_sh_safe_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]=' ';
-                       
-               /* 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_sh_safe_line_from_file(stdin);
-       }
-
-       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:
-*/
-