]>
git.saurik.com Git - apple/shell_cmds.git/blob - xargs/xargs.c
1 /* $NetBSD: xargs.c,v 1.10 1998/04/14 09:26:33 fair Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <sys/cdefs.h>
41 __COPYRIGHT("@(#) Copyright (c) 1990, 1993\n\
42 The Regents of the University of California. All rights reserved.\n");
47 static char sccsid
[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93";
49 __RCSID("$NetBSD: xargs.c,v 1.10 1998/04/14 09:26:33 fair Exp $");
52 #include <sys/types.h>
63 #include "pathnames.h"
65 int tflag
, zflag
, rval
;
67 void run
__P((char **));
68 int main
__P((int, char **));
69 void usage
__P((void));
77 char *p
, *bbp
, *ebp
, **bxp
, **exp
, **xp
;
78 int cnt
, indouble
, insingle
, nargs
, nflag
, nline
, xflag
;
81 setlocale(LC_ALL
, "");
84 * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
85 * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
86 * that the smallest argument is 2 bytes in length, this means that
87 * the number of arguments is limited to:
89 * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
91 * We arbitrarily limit the number of arguments to 5000. This is
92 * allowed by POSIX.2 as long as the resulting minimum exec line is
93 * at least LINE_MAX. Realloc'ing as necessary is possible, but
94 * probably not worthwhile.
97 nline
= ARG_MAX
- 4 * 1024;
99 while ((ch
= getopt(argc
, argv
, "0n:s:tx")) != -1)
106 if ((nargs
= atoi(optarg
)) <= 0)
107 errx(1, "illegal argument count");
110 nline
= atoi(optarg
);
129 * Allocate pointers for the utility name, the utility arguments,
130 * the maximum arguments to be read from stdin and the trailing
134 malloc((u_int
)(1 + argc
+ nargs
+ 1) * sizeof(char **))))
138 * Use the user's name for the utility as argv[0], just like the
139 * shell. Echo is the default. Set up pointers for the user's
143 cnt
= strlen(*bxp
++ = _PATH_ECHO
);
147 cnt
+= strlen(*bxp
++ = *argv
) + 1;
152 * Set up begin/end/traversing pointers into the array. The -n
153 * count doesn't include the trailing NULL pointer, so the malloc
154 * added in an extra slot.
156 exp
= (xp
= bxp
) + nargs
;
159 * Allocate buffer space for the arguments read from stdin and the
160 * trailing NULL. Buffer space is defined as the default or specified
161 * space, minus the length of the utility name and arguments. Set up
162 * begin/end/traversing pointers into the array. The -s count does
163 * include the trailing NULL, so the malloc didn't add in an extra
168 errx(1, "insufficient space for command");
170 if (!(bbp
= malloc((u_int
)nline
+ 1)))
172 ebp
= (argp
= p
= bbp
) + nline
- 1;
174 for (insingle
= indouble
= 0;;)
175 switch(ch
= getchar()) {
177 /* No arguments since last exec. */
181 /* Nothing since end of last argument. */
190 /* Quotes escape tabs and spaces. */
191 if (insingle
|| indouble
|| zflag
)
201 /* Empty lines are skipped. */
205 /* Quotes do not escape newlines. */
206 arg1
: if (insingle
|| indouble
)
207 errx(1, "unterminated quote");
213 * If max'd out on args or buffer, or reached EOF,
214 * run the command. If xflag and max'd out on buffer
215 * but not on args, object.
217 if (xp
== exp
|| p
== ebp
|| ch
== EOF
) {
218 if (xflag
&& xp
!= exp
&& p
== ebp
)
219 errx(1, "insufficient space for arguments");
231 if (indouble
|| zflag
)
233 insingle
= !insingle
;
236 if (insingle
|| zflag
)
238 indouble
= !indouble
;
243 /* Backslash escapes anything, is escaped by quotes. */
244 if (!insingle
&& !indouble
&& (ch
= getchar()) == EOF
)
245 errx(1, "backslash at EOF");
248 addch
: if (p
< ebp
) {
253 /* If only one argument, not enough buffer space. */
255 errx(1, "insufficient space for argument");
256 /* Didn't hit argument limit, so if xflag object. */
258 errx(1, "insufficient space for arguments");
264 memmove(bbp
, argp
, cnt
);
265 p
= (argp
= bbp
) + cnt
;
276 volatile int noinvoke
;
282 (void)fprintf(stderr
, "%s", *argv
);
283 for (p
= argv
+ 1; *p
; ++p
)
284 (void)fprintf(stderr
, " %s", *p
);
285 (void)fprintf(stderr
, "\n");
286 (void)fflush(stderr
);
289 switch(pid
= vfork()) {
293 execvp(argv
[0], argv
);
294 noinvoke
= (errno
== ENOENT
) ? 127 : 126;
295 warn("%s", argv
[0]);;
298 pid
= waitpid(pid
, &status
, 0);
303 * If we couldn't invoke the utility or the utility didn't exit
304 * properly, quit with 127 or 126 respectively.
310 * According to POSIX, we have to exit if the utility exits with
311 * a 255 status, or is interrupted by a signal. xargs is allowed
312 * to return any exit status between 1 and 125 in these cases, but
313 * we'll use 124 and 125, the same values used by GNU xargs.
315 if (WIFEXITED(status
)) {
316 if (WEXITSTATUS (status
) == 255) {
317 warnx ("%s exited with status 255", argv
[0]);
319 } else if (WEXITSTATUS (status
) != 0) {
322 } else if (WIFSIGNALED (status
)) {
324 if (WTERMSIG(status
) < NSIG
) {
326 if (WTERMSIG(status
) < _NSIG
) {
328 warnx("%s terminated by SIG%s", argv
[0],
329 sys_signame
[WTERMSIG(status
)]);
331 warnx("%s terminated by signal %d", argv
[0],
341 (void)fprintf(stderr
,
342 "usage: xargs [-0t] [-n number [-x]] [-s size] [utility [argument ...]]\n");