2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
40 All rights reserved.\n";
44 static char sccsid
[] = "@(#)xargs.c 5.11 (Berkeley) 6/19/91";
47 #include <sys/types.h>
58 #define _PATH_ECHO "/bin/echo"
60 #include "pathnames.h"
64 #define ARG_MAX (sizeof(int) == 2 ? 4096 : 128 * 1024)
69 void err(const char *, ...);
70 void run(char **argv
);
73 int main(int argc
, char **argv
)
78 register char *p
, *bbp
, *ebp
, **bxp
, **exp
, **xp
;
79 int cnt
, indouble
, insingle
, nargs
, nflag
, nline
, xflag
, zflag
;
83 * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
84 * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
85 * that the smallest argument is 2 bytes in length, this means that
86 * the number of arguments is limited to:
88 * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
90 * We arbitrarily limit the number of arguments to 5000. This is
91 * allowed by POSIX.2 as long as the resulting minimum exec line is
92 * at least LINE_MAX. Realloc'ing as necessary is possible, but
93 * probably not worthwhile.
95 #if !__minix || __minix_vmd
97 nline
= ARG_MAX
- 4 * 1024;
99 /* Things are more cramped under standard Minix. */
100 nargs
= 80 * sizeof(int);
101 nline
= ARG_MAX
- 512 * sizeof(int);
103 nflag
= xflag
= zflag
= 0;
104 while ((ch
= getopt(argc
, argv
, "n:s:tx0")) != EOF
)
108 if ((nargs
= atoi(optarg
)) <= 0)
109 err("illegal argument count");
112 nline
= atoi(optarg
);
134 * Allocate pointers for the utility name, the utility arguments,
135 * the maximum arguments to be read from stdin and the trailing
139 malloc((u_int
)(1 + argc
+ nargs
+ 1) * sizeof(char **))))
140 err("%s", strerror(errno
));
143 * Use the user's name for the utility as argv[0], just like the
144 * shell. Echo is the default. Set up pointers for the user's
148 cnt
= strlen(*bxp
++ = _PATH_ECHO
);
152 cnt
+= strlen(*bxp
++ = *argv
) + 1;
157 * Set up begin/end/traversing pointers into the array. The -n
158 * count doesn't include the trailing NULL pointer, so the malloc
159 * added in an extra slot.
161 exp
= (xp
= bxp
) + nargs
;
164 * Allocate buffer space for the arguments read from stdin and the
165 * trailing NULL. Buffer space is defined as the default or specified
166 * space, minus the length of the utility name and arguments. Set up
167 * begin/end/traversing pointers into the array. The -s count does
168 * include the trailing NULL, so the malloc didn't add in an extra
173 err("insufficient space for command");
175 if (!(bbp
= malloc((u_int
)nline
+ 1)))
176 err("%s", strerror(errno
));
177 ebp
= (argp
= p
= bbp
) + nline
- 1;
180 /* Read pathnames terminated by null bytes as produced by
181 * find ... -print0. No comments in this code, see further
185 switch(ch
= getchar()) {
203 if (xp
== exp
|| p
== ebp
|| ch
== EOF
) {
204 if (xflag
&& xp
!= exp
&& p
== ebp
)
206 "insufficient space for arguments");
224 err("insufficient space for argument");
226 err("insufficient space for arguments");
232 bcopy(argp
, bbp
, cnt
);
233 p
= (argp
= bbp
) + cnt
;
240 for (insingle
= indouble
= 0;;)
241 switch(ch
= getchar()) {
243 /* No arguments since last exec. */
247 /* Nothing since end of last argument. */
256 /* Quotes escape tabs and spaces. */
257 if (insingle
|| indouble
)
261 /* Empty lines are skipped. */
265 /* Quotes do not escape newlines. */
266 arg1
: if (insingle
|| indouble
)
267 err("unterminated quote");
273 * If max'd out on args or buffer, or reached EOF,
274 * run the command. If xflag and max'd out on buffer
275 * but not on args, object.
277 if (xp
== exp
|| p
== ebp
|| ch
== EOF
) {
278 if (xflag
&& xp
!= exp
&& p
== ebp
)
279 err("insufficient space for arguments");
293 insingle
= !insingle
;
298 indouble
= !indouble
;
301 /* Backslash escapes anything, is escaped by quotes. */
302 if (!insingle
&& !indouble
&& (ch
= getchar()) == EOF
)
303 err("backslash at EOF");
306 addch
: if (p
< ebp
) {
311 /* If only one argument, not enough buffer space. */
313 err("insufficient space for argument");
314 /* Didn't hit argument limit, so if xflag object. */
316 err("insufficient space for arguments");
322 bcopy(argp
, bbp
, cnt
);
323 p
= (argp
= bbp
) + cnt
;
330 void run(char **argv
)
339 (void)fprintf(stderr
, "%s", *argv
);
340 for (p
= argv
+ 1; *p
; ++p
)
341 (void)fprintf(stderr
, " %s", *p
);
342 (void)fprintf(stderr
, "\n");
343 (void)fflush(stderr
);
345 if (pipe(pfd
) < 0) err("pipe: %s", strerror(errno
));
347 switch(pid
= fork()) {
349 err("fork: %s", strerror(errno
));
352 fcntl(pfd
[1], F_SETFD
, fcntl(pfd
[1], F_GETFD
) | FD_CLOEXEC
);
354 execvp(argv
[0], argv
);
355 noinvoke
= (errno
== ENOENT
) ? 127 : 126;
356 (void)fprintf(stderr
,
357 "xargs: %s exec failed: %s.\n", argv
[0], strerror(errno
));
359 /* Modern way of returning noinvoke instead of a dirty vfork()
362 write(pfd
[1], &noinvoke
, sizeof(noinvoke
));
366 if (read(pfd
[0], &noinvoke
, sizeof(noinvoke
)) < sizeof(noinvoke
))
370 pid
= waitpid(pid
, &status
, 0);
372 err("waitpid: %s", strerror(errno
));
375 * If we couldn't invoke the utility or the utility didn't exit
376 * properly, quit with 127 or 126 respectively.
382 * According to POSIX, we have to exit if the utility exits with
383 * a 255 status, or is interrupted by a signal. xargs is allowed
384 * to return any exit status between 1 and 125 in these cases, but
385 * we'll use 124 and 125, the same values used by GNU xargs.
387 if (WIFEXITED(status
)) {
388 if (WEXITSTATUS (status
) == 255) {
389 fprintf (stderr
, "xargs: %s exited with status 255\n",
392 } else if (WEXITSTATUS (status
) != 0) {
395 } else if (WIFSTOPPED (status
)) {
396 fprintf (stderr
, "xargs: %s terminated by signal %d\n",
397 argv
[0], WSTOPSIG (status
));
399 } else if (WIFSIGNALED (status
)) {
400 fprintf (stderr
, "xargs: %s terminated by signal %d\n",
401 argv
[0], WTERMSIG (status
));
408 (void)fprintf(stderr
,
409 "usage: xargs [-t0] [[-x] -n number] [-s size] [utility [argument ...]]\n");
413 void err(const char *fmt
, ...)
418 (void)fprintf(stderr
, "xargs: ");
419 (void)vfprintf(stderr
, fmt
, ap
);
421 (void)fprintf(stderr
, "\n");