[BusyBox-cvs] busybox/findutils xargs.c,1.27,1.28

Glenn McGrath bug1 at busybox.net
Sat Oct 4 14:44:30 UTC 2003


Update of /var/cvs/busybox/findutils
In directory winder:/tmp/cvs-serv22941/findutils

Modified Files:
	xargs.c 
Log Message:
Add the x, n, s and E options, remove -r as its expected behaviour.


Index: xargs.c
===================================================================
RCS file: /var/cvs/busybox/findutils/xargs.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- xargs.c	3 Oct 2003 13:15:44 -0000	1.27
+++ xargs.c	4 Oct 2003 14:44:27 -0000	1.28
@@ -3,6 +3,7 @@
  * Only "-prt" options are supported in this version of xargs.
  *
  * (C) 2002 by Vladimir Oleynik <dzo at simtreas.ru>
+ * (C) 2003 by Glenn McGrath <bug1 at optushome.com.au>
  *
  * Special thanks Mark Whitley for stimul to rewrote :)
  *
@@ -20,12 +21,28 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * BUGS: -p doesnt accept user input
+ *
+ * Reference:
+ *	http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html
+ *
+ *
+ * BUGS:
+ *	p option doesnt accept user input, should read input from /dev/tty
+ *
+ *	E option doesnt allow spaces before argument
+ *
+ *	xargs should terminate if an invocation of a constructed command line
+ *  returns an exit status of 255.
+ *
+ *  exit value of isnt correct 
+ *
+ *  doesnt print quoted string properly
  *
  */
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <getopt.h>
 #include <errno.h>
@@ -33,7 +50,6 @@
 #include <sys/wait.h>
 #include "busybox.h"
 
-
 /*
    This function have special algorithm.
    Don`t use fork and include to main!
@@ -65,17 +81,42 @@
 
 #define OPT_VERBOSE	0x2
 #define OPT_INTERACTIVE	0x4
-#define OPT_NO_EMPTY	0x8
+#define OPT_TERMINATE	0x8
+#define OPT_UPTO_NUMBER	0x10
+#define OPT_UPTO_SIZE	0x20
+#define OPT_EOF_STRING	0x40
 
 int xargs_main(int argc, char **argv)
 {
-	char *file_to_act_on;
-	char **args;
-	int  i, a;
+	char *s_max_args = NULL;
+	char *s_line_size = NULL;
 	unsigned long flg;
 
+	char *eof_string = "_";
+	int line_size = LINE_MAX;
+	unsigned int max_args = LINE_MAX / 2;
+
+	char *line_buffer = NULL;
+	char *line_buffer_ptr_ptr;
+	char *old_arg = NULL;
+
+	char **args;
+	char *args_entry_ptr;
+
+	int i;
+	int a;
+
+	
 	bb_opt_complementaly = "pt";
-	flg = bb_getopt_ulflags(argc, argv, "+tpr");
+
+	flg = bb_getopt_ulflags(argc, argv, "+tpxn:s:E::", &s_max_args, &s_line_size, &eof_string);
+
+	if (s_max_args) {
+		max_args = bb_xgetularg10(s_max_args);
+	}
+	if (s_line_size) {
+		line_size = bb_xgetularg10(s_line_size);
+	}
 
 	a = argc - optind;
 	argv += optind;
@@ -88,20 +129,81 @@
 	args = xcalloc(a + 2, sizeof(char *));
 
 	/* Store the command to be executed (taken from the command line) */
-	for (i = 0; i < a; i++)
+	for (i = 0; i < a; i++) {
+		line_size -= strlen(*argv) + 1;
 		args[i] = *argv++;
+	}
+	if (line_size < 1) {
+		bb_error_msg_and_die("can not fit single argument within argument list size limit");
+	}
+
+	args[i] = xmalloc(line_size);
+	args_entry_ptr = args[i];
 
 	/* 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 & OPT_NO_EMPTY) == 0) {
-			args[a] = file_to_act_on[0] ? file_to_act_on : NULL;
+	do {
+		char *line_buffer_ptr = NULL;
+		unsigned int arg_count = 0;
+		unsigned int arg_size = 0;
+
+		*args_entry_ptr = '\0';
+
+		/* Get the required number of entries from stdin */
+		do {
+			/* (Re)fill the line buffer */
+			if (line_buffer == NULL) {
+				line_buffer = bb_get_chomped_line_from_file(stdin);
+				if (line_buffer == NULL) {
+					/* EOF, exit outer loop */
+					break;
+				}
+				line_buffer_ptr = strtok_r(line_buffer, " \t", &line_buffer_ptr_ptr);
+			} else {
+				if (old_arg) {
+					line_buffer_ptr = old_arg;
+					old_arg = NULL;
+				} else {
+					line_buffer_ptr = strtok_r(NULL, " \t", &line_buffer_ptr_ptr);
+				}
+			}
+			/* If no arguments left go back and get another line */
+			if (line_buffer_ptr == NULL) {
+				free(line_buffer);
+				line_buffer = NULL;
+				continue;
+			}
+
+			if (eof_string && (strcmp(line_buffer_ptr, eof_string) == 0)) {
+				/* logical EOF, exit outer loop */
+				line_buffer = NULL;
+				break;
+			}
+
+			/* Check the next argument will fit */
+			arg_size += 1 + strlen(line_buffer_ptr);
+			if (arg_size > line_size) {
+				if ((arg_count == 0) || ((flg & OPT_TERMINATE) && (arg_count != max_args))){
+					bb_error_msg_and_die("argument line too long");
+				}
+				old_arg = line_buffer_ptr;
+				break;
+			}
+
+			/* Add the entry to our pre-allocated space */
+			strcat(args_entry_ptr, line_buffer_ptr);
+			strcat(args_entry_ptr, " ");
+			arg_count++;
+		} while (arg_count < max_args);
+
+		if (*args_entry_ptr != '\0') {
 			if(flg & (OPT_VERBOSE | OPT_INTERACTIVE)) {
 				for(i=0; args[i]; i++) {
 					if(i)
 						fputc(' ', stderr);
 					fputs(args[i], stderr);
 				}
+
 				fputs(((flg & OPT_INTERACTIVE) ? " ?..." : "\n"), stderr);
 			}
 
@@ -109,9 +211,8 @@
 				xargs_exec(args);
 			}
 		}
-		/* clean up */
-		free(file_to_act_on);
-	}
+	} while (line_buffer);
+
 #ifdef CONFIG_FEATURE_CLEAN_UP
 	free(args);
 #endif




More information about the busybox-cvs mailing list