xargs.c revision 1.15 1 1.15 joerg /* $NetBSD: xargs.c,v 1.15 2006/03/28 14:27:41 joerg Exp $ */
2 1.7 jtc
3 1.1 cgd /*-
4 1.7 jtc * Copyright (c) 1990, 1993
5 1.7 jtc * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * This code is derived from software contributed to Berkeley by
8 1.1 cgd * John B. Roll Jr.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.14 agc * 3. Neither the name of the University nor the names of its contributors
19 1.1 cgd * may be used to endorse or promote products derived from this software
20 1.1 cgd * without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 cgd * SUCH DAMAGE.
33 1.1 cgd */
34 1.1 cgd
35 1.9 lukem #include <sys/cdefs.h>
36 1.1 cgd #ifndef lint
37 1.9 lukem __COPYRIGHT("@(#) Copyright (c) 1990, 1993\n\
38 1.9 lukem The Regents of the University of California. All rights reserved.\n");
39 1.1 cgd #endif /* not lint */
40 1.1 cgd
41 1.1 cgd #ifndef lint
42 1.7 jtc #if 0
43 1.7 jtc static char sccsid[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93";
44 1.7 jtc #endif
45 1.15 joerg __RCSID("$NetBSD: xargs.c,v 1.15 2006/03/28 14:27:41 joerg Exp $");
46 1.1 cgd #endif /* not lint */
47 1.1 cgd
48 1.1 cgd #include <sys/types.h>
49 1.1 cgd #include <sys/wait.h>
50 1.12 kleink #include <err.h>
51 1.1 cgd #include <errno.h>
52 1.12 kleink #include <langinfo.h>
53 1.12 kleink #include <limits.h>
54 1.12 kleink #include <locale.h>
55 1.12 kleink #include <paths.h>
56 1.12 kleink #include <regex.h>
57 1.12 kleink #include <signal.h>
58 1.1 cgd #include <stdio.h>
59 1.1 cgd #include <stdlib.h>
60 1.1 cgd #include <string.h>
61 1.1 cgd #include <unistd.h>
62 1.1 cgd #include "pathnames.h"
63 1.1 cgd
64 1.12 kleink static int pflag, tflag, zflag, rval;
65 1.12 kleink static FILE *promptfile;
66 1.12 kleink static regex_t yesexpr;
67 1.12 kleink
68 1.12 kleink static void run __P((char **));
69 1.12 kleink int main __P((int, char **));
70 1.12 kleink static void usage __P((void));
71 1.1 cgd
72 1.5 jtc int
73 1.1 cgd main(argc, argv)
74 1.1 cgd int argc;
75 1.1 cgd char **argv;
76 1.1 cgd {
77 1.9 lukem int ch;
78 1.9 lukem char *p, *bbp, *ebp, **bxp, **exp, **xp;
79 1.1 cgd int cnt, indouble, insingle, nargs, nflag, nline, xflag;
80 1.15 joerg long arg_max;
81 1.1 cgd char **av, *argp;
82 1.6 jtc
83 1.6 jtc setlocale(LC_ALL, "");
84 1.1 cgd
85 1.1 cgd /*
86 1.1 cgd * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
87 1.1 cgd * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
88 1.1 cgd * that the smallest argument is 2 bytes in length, this means that
89 1.1 cgd * the number of arguments is limited to:
90 1.1 cgd *
91 1.1 cgd * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
92 1.1 cgd *
93 1.1 cgd * We arbitrarily limit the number of arguments to 5000. This is
94 1.1 cgd * allowed by POSIX.2 as long as the resulting minimum exec line is
95 1.1 cgd * at least LINE_MAX. Realloc'ing as necessary is possible, but
96 1.1 cgd * probably not worthwhile.
97 1.1 cgd */
98 1.1 cgd nargs = 5000;
99 1.15 joerg if ((arg_max = sysconf(_SC_ARG_MAX)) == -1)
100 1.15 joerg errx(1, "sysconf(_SC_ARG_MAX) failed");
101 1.15 joerg nline = arg_max - 4 * 1024;
102 1.1 cgd nflag = xflag = 0;
103 1.12 kleink while ((ch = getopt(argc, argv, "0n:ps:tx")) != -1)
104 1.1 cgd switch(ch) {
105 1.8 lukem case '0':
106 1.8 lukem zflag = 1;
107 1.8 lukem break;
108 1.1 cgd case 'n':
109 1.1 cgd nflag = 1;
110 1.1 cgd if ((nargs = atoi(optarg)) <= 0)
111 1.7 jtc errx(1, "illegal argument count");
112 1.1 cgd break;
113 1.12 kleink case 'p':
114 1.12 kleink pflag = tflag = 1;
115 1.12 kleink break;
116 1.1 cgd case 's':
117 1.1 cgd nline = atoi(optarg);
118 1.1 cgd break;
119 1.1 cgd case 't':
120 1.1 cgd tflag = 1;
121 1.1 cgd break;
122 1.1 cgd case 'x':
123 1.1 cgd xflag = 1;
124 1.1 cgd break;
125 1.1 cgd case '?':
126 1.1 cgd default:
127 1.1 cgd usage();
128 1.1 cgd }
129 1.1 cgd argc -= optind;
130 1.1 cgd argv += optind;
131 1.1 cgd
132 1.1 cgd if (xflag && !nflag)
133 1.1 cgd usage();
134 1.1 cgd
135 1.1 cgd /*
136 1.1 cgd * Allocate pointers for the utility name, the utility arguments,
137 1.1 cgd * the maximum arguments to be read from stdin and the trailing
138 1.1 cgd * NULL.
139 1.1 cgd */
140 1.1 cgd if (!(av = bxp =
141 1.1 cgd malloc((u_int)(1 + argc + nargs + 1) * sizeof(char **))))
142 1.9 lukem err(1, "malloc");
143 1.1 cgd
144 1.1 cgd /*
145 1.1 cgd * Use the user's name for the utility as argv[0], just like the
146 1.1 cgd * shell. Echo is the default. Set up pointers for the user's
147 1.1 cgd * arguments.
148 1.1 cgd */
149 1.1 cgd if (!*argv)
150 1.1 cgd cnt = strlen(*bxp++ = _PATH_ECHO);
151 1.1 cgd else {
152 1.1 cgd cnt = 0;
153 1.1 cgd do {
154 1.1 cgd cnt += strlen(*bxp++ = *argv) + 1;
155 1.1 cgd } while (*++argv);
156 1.1 cgd }
157 1.1 cgd
158 1.1 cgd /*
159 1.1 cgd * Set up begin/end/traversing pointers into the array. The -n
160 1.1 cgd * count doesn't include the trailing NULL pointer, so the malloc
161 1.1 cgd * added in an extra slot.
162 1.1 cgd */
163 1.1 cgd exp = (xp = bxp) + nargs;
164 1.1 cgd
165 1.1 cgd /*
166 1.1 cgd * Allocate buffer space for the arguments read from stdin and the
167 1.1 cgd * trailing NULL. Buffer space is defined as the default or specified
168 1.1 cgd * space, minus the length of the utility name and arguments. Set up
169 1.1 cgd * begin/end/traversing pointers into the array. The -s count does
170 1.1 cgd * include the trailing NULL, so the malloc didn't add in an extra
171 1.1 cgd * slot.
172 1.1 cgd */
173 1.1 cgd nline -= cnt;
174 1.1 cgd if (nline <= 0)
175 1.7 jtc errx(1, "insufficient space for command");
176 1.1 cgd
177 1.1 cgd if (!(bbp = malloc((u_int)nline + 1)))
178 1.9 lukem err(1, "malloc");
179 1.1 cgd ebp = (argp = p = bbp) + nline - 1;
180 1.1 cgd
181 1.12 kleink if (pflag) {
182 1.12 kleink int error;
183 1.12 kleink
184 1.12 kleink if ((promptfile = fopen(_PATH_TTY, "r")) == NULL)
185 1.12 kleink err(1, "prompt mode: cannot open input");
186 1.12 kleink if ((error = regcomp(&yesexpr, nl_langinfo(YESEXPR), REG_NOSUB))
187 1.12 kleink != 0) {
188 1.12 kleink char msg[NL_TEXTMAX];
189 1.12 kleink
190 1.12 kleink (void)regerror(error, NULL, msg, sizeof (msg));
191 1.12 kleink err(1, "cannot compile yesexpr: %s", msg);
192 1.12 kleink }
193 1.12 kleink }
194 1.12 kleink
195 1.1 cgd for (insingle = indouble = 0;;)
196 1.1 cgd switch(ch = getchar()) {
197 1.1 cgd case EOF:
198 1.1 cgd /* No arguments since last exec. */
199 1.1 cgd if (p == bbp)
200 1.7 jtc exit(rval);
201 1.1 cgd
202 1.1 cgd /* Nothing since end of last argument. */
203 1.1 cgd if (argp == p) {
204 1.1 cgd *xp = NULL;
205 1.1 cgd run(av);
206 1.7 jtc exit(rval);
207 1.1 cgd }
208 1.1 cgd goto arg1;
209 1.1 cgd case ' ':
210 1.1 cgd case '\t':
211 1.1 cgd /* Quotes escape tabs and spaces. */
212 1.8 lukem if (insingle || indouble || zflag)
213 1.1 cgd goto addch;
214 1.1 cgd goto arg2;
215 1.8 lukem case '\0':
216 1.8 lukem if (zflag)
217 1.8 lukem goto arg2;
218 1.8 lukem goto addch;
219 1.1 cgd case '\n':
220 1.8 lukem if (zflag)
221 1.8 lukem goto addch;
222 1.1 cgd /* Empty lines are skipped. */
223 1.1 cgd if (argp == p)
224 1.1 cgd continue;
225 1.1 cgd
226 1.1 cgd /* Quotes do not escape newlines. */
227 1.1 cgd arg1: if (insingle || indouble)
228 1.7 jtc errx(1, "unterminated quote");
229 1.1 cgd
230 1.1 cgd arg2: *p = '\0';
231 1.1 cgd *xp++ = argp;
232 1.1 cgd
233 1.1 cgd /*
234 1.1 cgd * If max'd out on args or buffer, or reached EOF,
235 1.1 cgd * run the command. If xflag and max'd out on buffer
236 1.1 cgd * but not on args, object.
237 1.1 cgd */
238 1.1 cgd if (xp == exp || p == ebp || ch == EOF) {
239 1.1 cgd if (xflag && xp != exp && p == ebp)
240 1.7 jtc errx(1, "insufficient space for arguments");
241 1.1 cgd *xp = NULL;
242 1.1 cgd run(av);
243 1.1 cgd if (ch == EOF)
244 1.7 jtc exit(rval);
245 1.1 cgd p = bbp;
246 1.1 cgd xp = bxp;
247 1.1 cgd } else
248 1.1 cgd ++p;
249 1.1 cgd argp = p;
250 1.1 cgd break;
251 1.1 cgd case '\'':
252 1.8 lukem if (indouble || zflag)
253 1.1 cgd goto addch;
254 1.1 cgd insingle = !insingle;
255 1.1 cgd break;
256 1.1 cgd case '"':
257 1.8 lukem if (insingle || zflag)
258 1.1 cgd goto addch;
259 1.1 cgd indouble = !indouble;
260 1.1 cgd break;
261 1.1 cgd case '\\':
262 1.8 lukem if (zflag)
263 1.8 lukem goto addch;
264 1.1 cgd /* Backslash escapes anything, is escaped by quotes. */
265 1.1 cgd if (!insingle && !indouble && (ch = getchar()) == EOF)
266 1.7 jtc errx(1, "backslash at EOF");
267 1.1 cgd /* FALLTHROUGH */
268 1.1 cgd default:
269 1.1 cgd addch: if (p < ebp) {
270 1.1 cgd *p++ = ch;
271 1.1 cgd break;
272 1.1 cgd }
273 1.1 cgd
274 1.1 cgd /* If only one argument, not enough buffer space. */
275 1.1 cgd if (bxp == xp)
276 1.7 jtc errx(1, "insufficient space for argument");
277 1.1 cgd /* Didn't hit argument limit, so if xflag object. */
278 1.1 cgd if (xflag)
279 1.7 jtc errx(1, "insufficient space for arguments");
280 1.1 cgd
281 1.1 cgd *xp = NULL;
282 1.1 cgd run(av);
283 1.1 cgd xp = bxp;
284 1.1 cgd cnt = ebp - argp;
285 1.9 lukem memmove(bbp, argp, cnt);
286 1.1 cgd p = (argp = bbp) + cnt;
287 1.1 cgd *p++ = ch;
288 1.1 cgd break;
289 1.1 cgd }
290 1.1 cgd /* NOTREACHED */
291 1.1 cgd }
292 1.1 cgd
293 1.12 kleink static void
294 1.1 cgd run(argv)
295 1.1 cgd char **argv;
296 1.1 cgd {
297 1.7 jtc volatile int noinvoke;
298 1.9 lukem char **p;
299 1.1 cgd pid_t pid;
300 1.1 cgd int status;
301 1.1 cgd
302 1.1 cgd if (tflag) {
303 1.1 cgd (void)fprintf(stderr, "%s", *argv);
304 1.1 cgd for (p = argv + 1; *p; ++p)
305 1.1 cgd (void)fprintf(stderr, " %s", *p);
306 1.12 kleink if (pflag) {
307 1.12 kleink char buf[LINE_MAX + 1];
308 1.12 kleink
309 1.12 kleink (void)fprintf(stderr, "?...");
310 1.12 kleink fflush(stderr);
311 1.12 kleink if (fgets(buf, sizeof (buf), promptfile) == NULL) {
312 1.12 kleink rval = 1;
313 1.12 kleink return;
314 1.12 kleink }
315 1.12 kleink if (regexec(&yesexpr, buf, 0, NULL, 0) != 0)
316 1.12 kleink return;
317 1.12 kleink } else {
318 1.12 kleink (void)fprintf(stderr, "\n");
319 1.12 kleink }
320 1.1 cgd }
321 1.1 cgd noinvoke = 0;
322 1.1 cgd switch(pid = vfork()) {
323 1.1 cgd case -1:
324 1.7 jtc err(1, "vfork");
325 1.1 cgd case 0:
326 1.1 cgd execvp(argv[0], argv);
327 1.3 jtc noinvoke = (errno == ENOENT) ? 127 : 126;
328 1.13 simonb warn("%s", argv[0]);
329 1.1 cgd _exit(1);
330 1.1 cgd }
331 1.1 cgd pid = waitpid(pid, &status, 0);
332 1.1 cgd if (pid == -1)
333 1.7 jtc err(1, "waitpid");
334 1.3 jtc
335 1.1 cgd /*
336 1.1 cgd * If we couldn't invoke the utility or the utility didn't exit
337 1.3 jtc * properly, quit with 127 or 126 respectively.
338 1.3 jtc */
339 1.3 jtc if (noinvoke)
340 1.3 jtc exit(noinvoke);
341 1.3 jtc
342 1.3 jtc /*
343 1.3 jtc * According to POSIX, we have to exit if the utility exits with
344 1.3 jtc * a 255 status, or is interrupted by a signal. xargs is allowed
345 1.3 jtc * to return any exit status between 1 and 125 in these cases, but
346 1.3 jtc * we'll use 124 and 125, the same values used by GNU xargs.
347 1.1 cgd */
348 1.3 jtc if (WIFEXITED(status)) {
349 1.3 jtc if (WEXITSTATUS (status) == 255) {
350 1.7 jtc warnx ("%s exited with status 255", argv[0]);
351 1.3 jtc exit(124);
352 1.3 jtc } else if (WEXITSTATUS (status) != 0) {
353 1.7 jtc rval = 123;
354 1.3 jtc }
355 1.3 jtc } else if (WIFSIGNALED (status)) {
356 1.11 christos if (WTERMSIG(status) < NSIG) {
357 1.10 fair warnx("%s terminated by SIG%s", argv[0],
358 1.10 fair sys_signame[WTERMSIG(status)]);
359 1.10 fair } else {
360 1.10 fair warnx("%s terminated by signal %d", argv[0],
361 1.10 fair WTERMSIG(status));
362 1.10 fair }
363 1.3 jtc exit(125);
364 1.3 jtc }
365 1.1 cgd }
366 1.1 cgd
367 1.12 kleink static void
368 1.1 cgd usage()
369 1.1 cgd {
370 1.1 cgd (void)fprintf(stderr,
371 1.12 kleink "usage: xargs [-0pt] [-n number [-x]] [-s size] [utility [argument ...]]\n");
372 1.1 cgd exit(1);
373 1.1 cgd }
374