aboutsummaryrefslogtreecommitdiff
path: root/findutils/xargs.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2000-09-25 20:23:21 +0000
committerEric Andersen <andersen@codepoet.org>2000-09-25 20:23:21 +0000
commite081eae7a469e0ddeebedd51c3d83bcbaccb23e3 (patch)
tree0a3c6b650ee7f45d101bd6c7c289eaf63f3d6607 /findutils/xargs.c
parentbf73909f23a00bdcc4f4e12459c64b99b2ebcddb (diff)
downloadbusybox-w32-e081eae7a469e0ddeebedd51c3d83bcbaccb23e3.tar.gz
busybox-w32-e081eae7a469e0ddeebedd51c3d83bcbaccb23e3.tar.bz2
busybox-w32-e081eae7a469e0ddeebedd51c3d83bcbaccb23e3.zip
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/xargs.c')
-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 @@
28#include <errno.h> 28#include <errno.h>
29#include <getopt.h> 29#include <getopt.h>
30#include <ctype.h> 30#include <ctype.h>
31 31#include <sys/types.h>
32/* get_sh_safe_line_from_file() - This function reads an entire line from a text file 32#include <sys/wait.h>
33 * up to a newline. It returns a malloc'ed char * which must be stored and
34 * free'ed by the caller. */
35extern char *get_sh_safe_line_from_file(FILE *file)
36{
37 static const int GROWBY = 80; /* how large we will grow strings by */
38
39 char ch, last_ch = 0;
40 char tmp[]=" ";
41 int idx = 0;
42 char *linebuf = NULL;
43 int linebufsz = 0;
44
45 while (1) {
46 ch = fgetc(file);
47 if (ch == EOF)
48 break;
49
50 /* grow the line buffer as necessary */
51 while (idx > linebufsz-4)
52 linebuf = xrealloc(linebuf, linebufsz += GROWBY);
53
54 /* Remove any extra spaces */
55 if (last_ch == ' ' && ch == ' ')
56 continue;
57
58 /* Replace any tabs with spaces */
59 if (ch == '\t')
60 ch=' ';
61
62 /* Escape any characters that are treated specially by /bin/sh */
63 *tmp=ch;
64 if (strpbrk(tmp, "\\~`!$^&*()=|{}[];\"'<>?#") != NULL && last_ch!='\\') {
65 linebuf[idx++] = '\\';
66 }
67
68 linebuf[idx++] = ch;
69 last_ch=ch;
70
71 if (ch == '\n')
72 break;
73 }
74 if (idx == 0 && last_ch!=0)
75 linebuf[idx++]=' ';
76
77 if (idx == 0)
78 return NULL;
79
80 linebuf[idx] = 0;
81 return linebuf;
82}
83
84 33
85 34
86int xargs_main(int argc, char **argv) 35int xargs_main(int argc, char **argv)
87{ 36{
88 char *in_from_stdin = NULL; 37 char *in_from_stdin = NULL;
89 char *args_from_cmdline = NULL; 38 char *args = NULL;
90 char *cmd_to_be_executed = NULL; 39 char *cmd_to_be_executed = NULL;
91 char traceflag = 0; 40 char traceflag = 0;
92 int len_args_from_cmdline, len_cmd_to_be_executed, len, opt; 41 int len_args=10, len_cmd_to_be_executed, opt;
42 pid_t pid;
43 int wpid, status;
93 44
94 /* Note that we do not use getopt here, since 45 /* Note that we do not use getopt here, since
95 * we only want to interpret initial options, 46 * we only want to interpret initial options,
@@ -102,50 +53,45 @@ int xargs_main(int argc, char **argv)
102 break; 53 break;
103 default: 54 default:
104 fatalError(xargs_usage); 55 fatalError(xargs_usage);
105 } 56 }
106 } 57 }
107 } 58 }
108 59
109 /* Store the command and arguments to be executed (from the command line) */ 60 /* Store the command to be executed (taken from the command line) */
110 if (argc == 0) { 61 if (argc == 0) {
111 len_args_from_cmdline = 6; 62 len_cmd_to_be_executed=6;
112 args_from_cmdline = xmalloc(len_args_from_cmdline); 63 cmd_to_be_executed = xmalloc(len_cmd_to_be_executed);
113 strcat(args_from_cmdline, "echo "); 64 strcat(cmd_to_be_executed, "echo");
114 } else { 65 } else {
115 opt=strlen(*argv); 66 opt=strlen(*argv);
116 len_args_from_cmdline = (opt > 10)? opt : 10; 67 len_cmd_to_be_executed = (opt > 10)? opt : 10;
117 args_from_cmdline = xcalloc(len_args_from_cmdline, sizeof(char)); 68 cmd_to_be_executed = xcalloc(len_cmd_to_be_executed, sizeof(char));
118 while (argc-- > 0) { 69 strcat(cmd_to_be_executed, *argv);
119 if (strlen(*argv) + strlen(args_from_cmdline) >
120 len_args_from_cmdline) {
121 len_args_from_cmdline += strlen(*argv);
122 args_from_cmdline =
123 xrealloc(args_from_cmdline,
124 len_args_from_cmdline+1);
125 }
126 strcat(args_from_cmdline, *argv);
127 strcat(args_from_cmdline, " ");
128 ++argv;
129 }
130 } 70 }
131 71
132 /* Set up some space for the command to be executed to be held in */
133 len_cmd_to_be_executed=10;
134 cmd_to_be_executed = xcalloc(len_cmd_to_be_executed, sizeof(char));
135 strcpy(cmd_to_be_executed, args_from_cmdline);
136 72
137 /* Now, read in one line at a time from stdin, and run command+args on it */ 73 /* Now, read in one line at a time from stdin, and stroe this to be used later
138 in_from_stdin = get_sh_safe_line_from_file(stdin); 74 * as an argument to the command we just stored */
75 in_from_stdin = get_line_from_file(stdin);
139 for (;in_from_stdin!=NULL;) { 76 for (;in_from_stdin!=NULL;) {
140 char *tmp; 77 char *tmp;
141 opt = strlen(in_from_stdin); 78 opt = strlen(in_from_stdin);
142 len = opt + len_args_from_cmdline; 79 len_args += opt + 3;
143 len_cmd_to_be_executed+=len+3; 80 args=xrealloc(args, len_args);
144 cmd_to_be_executed=xrealloc(cmd_to_be_executed, len_cmd_to_be_executed);
145 81
146 /* Strip out the final \n */ 82 /* Strip out the final \n */
147 in_from_stdin[opt-1]=' '; 83 in_from_stdin[opt-1]=' ';
148 84
85 /* Replace any tabs with spaces */
86 while( (tmp = strchr(in_from_stdin, '\t')) != NULL )
87 *tmp=' ';
88
89 /* Strip out any extra intra-word spaces */
90 while( (tmp = strstr(in_from_stdin, " ")) != NULL ) {
91 opt = strlen(in_from_stdin);
92 memmove(tmp, tmp+1, opt-(tmp-in_from_stdin));
93 }
94
149 /* trim trailing whitespace */ 95 /* trim trailing whitespace */
150 opt = strlen(in_from_stdin) - 1; 96 opt = strlen(in_from_stdin) - 1;
151 while (isspace(in_from_stdin[opt])) 97 while (isspace(in_from_stdin[opt]))
@@ -157,26 +103,49 @@ int xargs_main(int argc, char **argv)
157 while(isspace(*tmp)) 103 while(isspace(*tmp))
158 tmp++; 104 tmp++;
159 105
160 strcat(cmd_to_be_executed, tmp); 106 strcat(args, tmp);
161 strcat(cmd_to_be_executed, " "); 107 strcat(args, " ");
162 108
163 free(in_from_stdin); 109 free(in_from_stdin);
164 in_from_stdin = get_sh_safe_line_from_file(stdin); 110 in_from_stdin = get_line_from_file(stdin);
165 } 111 }
166 112
167 if (traceflag==1) 113 if (traceflag==1) {
168 fputs(cmd_to_be_executed, stderr); 114 fputs(cmd_to_be_executed, stderr);
115 fputs(args, stderr);
116 }
169 117
170 if ((system(cmd_to_be_executed) != 0) && (errno != 0)) 118 if ((pid = fork()) == 0) {
171 fatalError("%s", strerror(errno)); 119 char *cmd[255];
120 int i=1;
121
122 //printf("argv[0]='%s'\n", cmd_to_be_executed);
123 cmd[0] = cmd_to_be_executed;
124 while (--argc && ++argv && *argv ) {
125 //printf("argv[%d]='%s'\n", i, *argv);
126 cmd[i++]=*argv;
127 }
128 //printf("argv[%d]='%s'\n", i, args);
129 cmd[i++] = args;
130 cmd[i] = NULL;
131 execvp(cmd_to_be_executed, cmd);
132
133 /* What? Still here? Exit with an error */
134 fatalError("%s: %s\n", cmd_to_be_executed, strerror(errno));
135 }
136 /* Wait for a child process to exit */
137 wpid = wait(&status);
172 138
173 139
174#ifdef BB_FEATURE_CLEAN_UP 140#ifdef BB_FEATURE_CLEAN_UP
175 free(args_from_cmdline); 141 free(args);
176 free(cmd_to_be_executed); 142 free(cmd_to_be_executed);
177#endif 143#endif
178 144
179 return 0; 145 if (wpid > 0)
146 return (WEXITSTATUS(status));
147 else
148 return EXIT_FAILURE;
180} 149}
181/* 150/*
182Local Variables: 151Local Variables:
@@ -185,4 +154,3 @@ c-basic-offset: 4
185tab-width: 4 154tab-width: 4
186End: 155End:
187*/ 156*/
188