last_patch95 from vodz:
[oweals/busybox.git] / findutils / xargs.c
index beada7a15412222d1bfee902d2ab167d90fbe6d2..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 "busybox.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 = NULL;
-       char *cmd_to_be_executed = NULL;
-       char traceflag = 0;
-       int len_args=2, len_cmd_to_be_executed, opt;
-       pid_t pid;
-       int wpid, status;
-
-       /* 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);
+       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]);
                        }
                }
+       } else {
+               bb_perror_msg_and_die("vfork");
        }
+}
 
-       /* Store the command to be executed (taken from the command line) */
-       if (argc == 0) {
-               len_cmd_to_be_executed=6;
-               cmd_to_be_executed = xmalloc(len_cmd_to_be_executed);
-               strcat(cmd_to_be_executed, "echo");
-       } else {
-               opt=strlen(*argv);
-               len_cmd_to_be_executed = (opt > 10)? opt : 10;
-               cmd_to_be_executed = xcalloc(len_cmd_to_be_executed, sizeof(char));
-               strcat(cmd_to_be_executed, *argv);
+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 *));
 
-       args=xrealloc(args, len_args);
-       strcpy(args, " ");
+       /* 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 */
-       in_from_stdin = get_line_from_file(stdin);
-       for (;in_from_stdin!=NULL;) {
-               char *tmp;
-               opt = strlen(in_from_stdin);
-               len_args += opt + 3;
-               args=xrealloc(args, len_args);
-
-               /* 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));
-               }
-
-               /* 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(args, tmp);
-               strcat(args, " ");
-
-               free(in_from_stdin);
-               in_from_stdin = get_line_from_file(stdin);
-       }
-
-       if (traceflag==1) {
-               fprintf(stderr, "%s%s\n", cmd_to_be_executed, args);
-       }
-
-       if ((pid = fork()) == 0) {
-               char *cmd[255];
-               int i=1;
-
-               //printf("argv[0]='%s'\n", cmd_to_be_executed);
-               cmd[0] = cmd_to_be_executed;
-               while (--argc && ++argv && *argv ) {
-                       //printf("argv[%d]='%s'\n", i, *argv);
-                       cmd[i++]=*argv;
+       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);
+                       }
                }
-               //printf("argv[%d]='%s'\n", i, args);
-               cmd[i++] = args;
-               cmd[i] = NULL;
-               execvp(cmd_to_be_executed, cmd);
-
-               /* What?  Still here?  Exit with an error */
-               fatalError("%s: %s\n", cmd_to_be_executed, strerror(errno));
+               /* clean up */
+               free(file_to_act_on);
        }
-       /* Wait for a child process to exit */
-       wpid = wait(&status);
-
-
-#ifdef BB_FEATURE_CLEAN_UP
+#ifdef CONFIG_FEATURE_CLEAN_UP
        free(args);
-       free(cmd_to_be_executed);
 #endif
-
-       if (wpid > 0)
-               return (WEXITSTATUS(status));
-       else 
-               return EXIT_FAILURE;
+       return 0;
 }
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/