Add the x, n, s and E options, remove -r as its expected behaviour.
No binary (build failed)
—
(log yok)
| @@ -3,6 +3,7 @@ | |
| * Only "-prt" options are supported in this version of xargs. | |
| * | |
| * (C) 2002 by Vladimir Oleynik <[email protected]> | |
| + | * (C) 2003 by Glenn McGrath <[email protected]> |
| * | |
| * 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 @@ static void xargs_exec(char * const * args) | |
| #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 @@ int xargs_main(int argc, char **argv) | |
| 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 @@ int xargs_main(int argc, char **argv) | |
| xargs_exec(args); | |
| } | |
| } | |
| - | /* clean up */ |
| - | free(file_to_act_on); |
| - | } |
| + | } while (line_buffer); |
| + | |
| #ifdef CONFIG_FEATURE_CLEAN_UP | |
| free(args); | |
| #endif | |