Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.busybox.net/busybox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2000-09-26 00:23:21 +0400
committerEric Andersen <andersen@codepoet.org>2000-09-26 00:23:21 +0400
commite081eae7a469e0ddeebedd51c3d83bcbaccb23e3 (patch)
tree0a3c6b650ee7f45d101bd6c7c289eaf63f3d6607 /findutils
parentbf73909f23a00bdcc4f4e12459c64b99b2ebcddb (diff)
Final (I think) version of xargs. Throw away all that tedious string
scrubbing, and quit using system. Instead, use fork() and exec(), which yields and smaller, simpler, and cleaner design. -Erik
Diffstat (limited to 'findutils')
-rw-r--r--findutils/xargs.c156
1 files changed, 62 insertions, 94 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 21bfb6bbe..b8ac31aa0 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -28,68 +28,19 @@
#include <errno.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;
-
- /* 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++] = '\\';
- }
-
- linebuf[idx++] = ch;
- last_ch=ch;
-
- if (ch == '\n')
- break;
- }
- if (idx == 0 && last_ch!=0)
- linebuf[idx++]=' ';
-
- if (idx == 0)
- return NULL;
-
- linebuf[idx] = 0;
- return linebuf;
-}
-
+#include <sys/types.h>
+#include <sys/wait.h>
int xargs_main(int argc, char **argv)
{
char *in_from_stdin = NULL;
- char *args_from_cmdline = NULL;
+ char *args = NULL;
char *cmd_to_be_executed = NULL;
char traceflag = 0;
- int len_args_from_cmdline, len_cmd_to_be_executed, len, opt;
+ int len_args=10, 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,
@@ -102,50 +53,45 @@ int xargs_main(int argc, char **argv)
break;
default:
fatalError(xargs_usage);
- }
+ }
}
}
- /* Store the command and arguments to be executed (from the command line) */
+ /* Store the command to be executed (taken 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 ");
+ 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_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);
- }
- strcat(args_from_cmdline, *argv);
- strcat(args_from_cmdline, " ");
- ++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);
}
- /* 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);
+ /* Now, read in one line at a time from stdin, and stroe this to be used later
+ * as an argument to the command we just stored */
+ 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);
+ 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]))
@@ -157,26 +103,49 @@ int xargs_main(int argc, char **argv)
while(isspace(*tmp))
tmp++;
- strcat(cmd_to_be_executed, tmp);
- strcat(cmd_to_be_executed, " ");
-
+ strcat(args, tmp);
+ strcat(args, " ");
+
free(in_from_stdin);
- in_from_stdin = get_sh_safe_line_from_file(stdin);
+ in_from_stdin = get_line_from_file(stdin);
}
- if (traceflag==1)
+ if (traceflag==1) {
fputs(cmd_to_be_executed, stderr);
+ fputs(args, stderr);
+ }
- if ((system(cmd_to_be_executed) != 0) && (errno != 0))
- fatalError("%s", strerror(errno));
+ 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;
+ }
+ //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));
+ }
+ /* Wait for a child process to exit */
+ wpid = wait(&status);
#ifdef BB_FEATURE_CLEAN_UP
- free(args_from_cmdline);
+ free(args);
free(cmd_to_be_executed);
#endif
- return 0;
+ if (wpid > 0)
+ return (WEXITSTATUS(status));
+ else
+ return EXIT_FAILURE;
}
/*
Local Variables:
@@ -185,4 +154,3 @@ c-basic-offset: 4
tab-width: 4
End:
*/
-