Annotation of src/usr.bin/xargs/xargs.c, Revision 1.27
1.27 ! schwarze 1: /* $OpenBSD: xargs.c,v 1.26 2009/10/27 23:59:50 deraadt Exp $ */
1.14 millert 2: /* $FreeBSD: xargs.c,v 1.51 2003/05/03 19:09:11 obrien Exp $ */
1.1 deraadt 3:
4: /*-
5: * Copyright (c) 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * John B. Roll Jr.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
1.12 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
1.14 millert 34: *
35: * $xMach: xargs.c,v 1.6 2002/02/23 05:27:47 tim Exp $
1.1 deraadt 36: */
37:
1.14 millert 38: #include <sys/param.h>
1.1 deraadt 39: #include <sys/wait.h>
1.14 millert 40:
1.27 ! schwarze 41: #include <ctype.h>
1.14 millert 42: #include <err.h>
1.1 deraadt 43: #include <errno.h>
1.14 millert 44: #include <fcntl.h>
45: #include <langinfo.h>
46: #include <locale.h>
47: #include <paths.h>
48: #include <regex.h>
49: #include <signal.h>
1.1 deraadt 50: #include <stdio.h>
51: #include <stdlib.h>
52: #include <string.h>
53: #include <unistd.h>
1.14 millert 54:
1.1 deraadt 55: #include "pathnames.h"
56:
1.14 millert 57: static void parse_input(int, char *[]);
58: static void prerun(int, char *[]);
59: static int prompt(void);
60: static void run(char **);
61: static void usage(void);
62: void strnsubst(char **, const char *, const char *, size_t);
63: static void waitchildren(const char *, int);
64:
65: static char **av, **bxp, **ep, **endxp, **xp;
66: static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
67: static const char *eofstr;
68: static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag;
1.21 brad 69: static int cnt, Iflag, jfound, Lflag, wasquoted, xflag, runeof = 1;
1.14 millert 70: static int curprocs, maxprocs;
71: static size_t inpsize;
72:
73: extern char **environ;
1.1 deraadt 74:
75: int
1.13 deraadt 76: main(int argc, char *argv[])
1.1 deraadt 77: {
1.14 millert 78: long arg_max;
79: int ch, Jflag, nargs, nflag, nline;
80: size_t linelen;
81: char *endptr;
82:
83: inpline = replstr = NULL;
84: ep = environ;
85: eofstr = "";
86: Jflag = nflag = 0;
1.1 deraadt 87:
1.14 millert 88: (void)setlocale(LC_MESSAGES, "");
1.1 deraadt 89:
90: /*
91: * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
92: * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
93: * that the smallest argument is 2 bytes in length, this means that
94: * the number of arguments is limited to:
95: *
96: * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
97: *
98: * We arbitrarily limit the number of arguments to 5000. This is
99: * allowed by POSIX.2 as long as the resulting minimum exec line is
100: * at least LINE_MAX. Realloc'ing as necessary is possible, but
101: * probably not worthwhile.
102: */
103: nargs = 5000;
1.8 deraadt 104: if ((arg_max = sysconf(_SC_ARG_MAX)) == -1)
105: errx(1, "sysconf(_SC_ARG_MAX) failed");
106: nline = arg_max - 4 * 1024;
1.14 millert 107: while (*ep != NULL) {
108: /* 1 byte for each '\0' */
109: nline -= strlen(*ep++) + 1 + sizeof(*ep);
110: }
111: maxprocs = 1;
1.21 brad 112: while ((ch = getopt(argc, argv, "0E:I:J:L:n:oP:pR:rs:tx")) != -1)
1.20 millert 113: switch (ch) {
1.14 millert 114: case 'E':
115: eofstr = optarg;
116: break;
117: case 'I':
118: Jflag = 0;
119: Iflag = 1;
120: Lflag = 1;
121: replstr = optarg;
122: break;
123: case 'J':
124: Iflag = 0;
125: Jflag = 1;
126: replstr = optarg;
127: break;
128: case 'L':
129: Lflag = atoi(optarg);
130: break;
1.1 deraadt 131: case 'n':
132: nflag = 1;
133: if ((nargs = atoi(optarg)) <= 0)
134: errx(1, "illegal argument count");
135: break;
1.14 millert 136: case 'o':
137: oflag = 1;
138: break;
139: case 'P':
140: if ((maxprocs = atoi(optarg)) <= 0)
141: errx(1, "max. processes must be >0");
142: break;
143: case 'p':
144: pflag = 1;
145: break;
1.21 brad 146: case 'r':
147: runeof = 0;
148: break;
1.14 millert 149: case 'R':
150: Rflag = strtol(optarg, &endptr, 10);
151: if (*endptr != '\0')
152: errx(1, "replacements must be a number");
153: break;
1.1 deraadt 154: case 's':
155: nline = atoi(optarg);
156: break;
157: case 't':
158: tflag = 1;
159: break;
160: case 'x':
161: xflag = 1;
162: break;
1.2 deraadt 163: case '0':
164: zflag = 1;
165: break;
1.1 deraadt 166: case '?':
167: default:
168: usage();
169: }
170: argc -= optind;
171: argv += optind;
172:
1.14 millert 173: if (!Iflag && Rflag)
174: usage();
175: if (Iflag && !Rflag)
176: Rflag = 5;
177: if (xflag && !nflag)
178: usage();
179: if (Iflag || Lflag)
180: xflag = 1;
181: if (replstr != NULL && *replstr == '\0')
182: errx(1, "replstr may not be empty");
183:
1.1 deraadt 184: /*
185: * Allocate pointers for the utility name, the utility arguments,
186: * the maximum arguments to be read from stdin and the trailing
187: * NULL.
188: */
1.14 millert 189: linelen = 1 + argc + nargs + 1;
1.25 deraadt 190: if ((av = bxp = calloc(linelen, sizeof(char **))) == NULL)
1.1 deraadt 191: err(1, NULL);
192:
193: /*
194: * Use the user's name for the utility as argv[0], just like the
195: * shell. Echo is the default. Set up pointers for the user's
196: * arguments.
197: */
1.14 millert 198: if (*argv == NULL)
1.1 deraadt 199: cnt = strlen(*bxp++ = _PATH_ECHO);
200: else {
201: do {
1.14 millert 202: if (Jflag && strcmp(*argv, replstr) == 0) {
203: char **avj;
204: jfound = 1;
205: argv++;
206: for (avj = argv; *avj; avj++)
207: cnt += strlen(*avj) + 1;
208: break;
209: }
1.1 deraadt 210: cnt += strlen(*bxp++ = *argv) + 1;
1.14 millert 211: } while (*++argv != NULL);
1.1 deraadt 212: }
213:
214: /*
215: * Set up begin/end/traversing pointers into the array. The -n
216: * count doesn't include the trailing NULL pointer, so the malloc
217: * added in an extra slot.
218: */
1.14 millert 219: endxp = (xp = bxp) + nargs;
1.1 deraadt 220:
221: /*
222: * Allocate buffer space for the arguments read from stdin and the
223: * trailing NULL. Buffer space is defined as the default or specified
224: * space, minus the length of the utility name and arguments. Set up
225: * begin/end/traversing pointers into the array. The -s count does
226: * include the trailing NULL, so the malloc didn't add in an extra
227: * slot.
228: */
229: nline -= cnt;
230: if (nline <= 0)
231: errx(1, "insufficient space for command");
232:
1.14 millert 233: if ((bbp = malloc((size_t)(nline + 1))) == NULL)
1.18 millert 234: err(1, NULL);
1.1 deraadt 235: ebp = (argp = p = bbp) + nline - 1;
1.14 millert 236: for (;;)
237: parse_input(argc, argv);
238: }
239:
240: static void
241: parse_input(int argc, char *argv[])
242: {
1.27 ! schwarze 243: int hasblank = 0;
! 244: static int hadblank = 0;
1.20 millert 245: int ch, foundeof = 0;
1.14 millert 246: char **avj;
1.1 deraadt 247:
1.27 ! schwarze 248: ch = getchar();
! 249: if (isblank(ch)) {
! 250: /* Quotes escape tabs and spaces. */
! 251: if (insingle || indouble)
! 252: goto addch;
! 253: hasblank = 1;
! 254: if (zflag)
! 255: goto addch;
! 256: goto arg2;
! 257: }
! 258:
! 259: switch (ch) {
1.14 millert 260: case EOF:
261: /* No arguments since last exec. */
262: if (p == bbp) {
1.21 brad 263: if (runeof)
264: prerun(0, av);
1.14 millert 265: waitchildren(*argv, 1);
266: exit(rval);
267: }
268: goto arg1;
269: case '\0':
270: if (zflag)
1.1 deraadt 271: goto arg2;
1.14 millert 272: goto addch;
273: case '\n':
1.27 ! schwarze 274: hasblank = 1;
! 275: if (hadblank == 0)
! 276: count++;
1.14 millert 277: if (zflag)
1.2 deraadt 278: goto addch;
1.1 deraadt 279:
1.14 millert 280: /* Quotes do not escape newlines. */
281: arg1: if (insingle || indouble)
282: errx(1, "unterminated quote");
283: arg2:
284: foundeof = *eofstr != '\0' &&
285: strcmp(argp, eofstr) == 0;
286:
287: /* Do not make empty args unless they are quoted */
288: if ((argp != p || wasquoted) && !foundeof) {
289: *p++ = '\0';
1.1 deraadt 290: *xp++ = argp;
1.14 millert 291: if (Iflag) {
292: size_t curlen;
1.1 deraadt 293:
1.14 millert 294: if (inpline == NULL)
295: curlen = 0;
296: else {
297: /*
298: * If this string is not zero
299: * length, append a space for
300: * separation before the next
301: * argument.
302: */
303: if ((curlen = strlen(inpline)))
304: strlcat(inpline, " ", inpsize);
305: }
306: curlen++;
307: /*
308: * Allocate enough to hold what we will
309: * be holding in a second, and to append
310: * a space next time through, if we have
311: * to.
312: */
313: inpsize = curlen + 2 + strlen(argp);
314: inpline = realloc(inpline, inpsize);
315: if (inpline == NULL)
316: errx(1, "realloc failed");
317: if (curlen == 1)
318: strlcpy(inpline, argp, inpsize);
319: else
320: strlcat(inpline, argp, inpsize);
1.1 deraadt 321: }
1.14 millert 322: }
1.1 deraadt 323:
1.14 millert 324: /*
325: * If max'd out on args or buffer, or reached EOF,
326: * run the command. If xflag and max'd out on buffer
327: * but not on args, object. Having reached the limit
328: * of input lines, as specified by -L is the same as
329: * maxing out on arguments.
330: */
331: if (xp == endxp || p > ebp || ch == EOF ||
332: (Lflag <= count && xflag) || foundeof) {
333: if (xflag && xp != endxp && p > ebp)
1.1 deraadt 334: errx(1, "insufficient space for arguments");
1.14 millert 335: if (jfound) {
336: for (avj = argv; *avj; avj++)
337: *xp++ = *avj;
338: }
339: prerun(argc, av);
340: if (ch == EOF || foundeof) {
341: waitchildren(*argv, 1);
342: exit(rval);
343: }
344: p = bbp;
1.1 deraadt 345: xp = bxp;
1.14 millert 346: count = 0;
347: }
348: argp = p;
349: wasquoted = 0;
350: break;
351: case '\'':
352: if (indouble || zflag)
353: goto addch;
354: insingle = !insingle;
355: wasquoted = 1;
356: break;
357: case '"':
358: if (insingle || zflag)
359: goto addch;
360: indouble = !indouble;
361: wasquoted = 1;
362: break;
363: case '\\':
364: if (zflag)
365: goto addch;
366: /* Backslash escapes anything, is escaped by quotes. */
367: if (!insingle && !indouble && (ch = getchar()) == EOF)
368: errx(1, "backslash at EOF");
369: /* FALLTHROUGH */
370: default:
371: addch: if (p < ebp) {
1.1 deraadt 372: *p++ = ch;
373: break;
374: }
1.14 millert 375:
376: /* If only one argument, not enough buffer space. */
377: if (bxp == xp)
378: errx(1, "insufficient space for argument");
379: /* Didn't hit argument limit, so if xflag object. */
380: if (xflag)
381: errx(1, "insufficient space for arguments");
382:
383: if (jfound) {
384: for (avj = argv; *avj; avj++)
385: *xp++ = *avj;
386: }
387: prerun(argc, av);
388: xp = bxp;
389: cnt = ebp - argp;
390: memcpy(bbp, argp, (size_t)cnt);
391: p = (argp = bbp) + cnt;
392: *p++ = ch;
393: break;
394: }
1.27 ! schwarze 395: hadblank = hasblank;
1.1 deraadt 396: }
397:
1.14 millert 398: /*
399: * Do things necessary before run()'ing, such as -I substitution,
400: * and then call run().
401: */
402: static void
403: prerun(int argc, char *argv[])
404: {
405: char **tmp, **tmp2, **avj;
406: int repls;
407:
408: repls = Rflag;
1.21 brad 409: runeof = 0;
1.14 millert 410:
411: if (argc == 0 || repls == 0) {
412: *xp = NULL;
413: run(argv);
414: return;
415: }
416:
417: avj = argv;
418:
419: /*
420: * Allocate memory to hold the argument list, and
421: * a NULL at the tail.
422: */
1.25 deraadt 423: tmp = calloc(argc + 1, sizeof(char**));
1.14 millert 424: if (tmp == NULL)
1.18 millert 425: err(1, NULL);
1.14 millert 426: tmp2 = tmp;
427:
428: /*
429: * Save the first argument and iterate over it, we
430: * cannot do strnsubst() to it.
431: */
432: if ((*tmp++ = strdup(*avj++)) == NULL)
1.18 millert 433: err(1, NULL);
1.14 millert 434:
435: /*
436: * For each argument to utility, if we have not used up
437: * the number of replacements we are allowed to do, and
438: * if the argument contains at least one occurrence of
439: * replstr, call strnsubst(), else just save the string.
440: * Iterations over elements of avj and tmp are done
441: * where appropriate.
442: */
443: while (--argc) {
444: *tmp = *avj++;
445: if (repls && strstr(*tmp, replstr) != NULL) {
446: strnsubst(tmp++, replstr, inpline, (size_t)255);
447: if (repls > 0)
448: repls--;
449: } else {
450: if ((*tmp = strdup(*tmp)) == NULL)
1.18 millert 451: err(1, NULL);
1.14 millert 452: tmp++;
453: }
454: }
455:
456: /*
457: * Run it.
458: */
459: *tmp = NULL;
460: run(tmp2);
461:
462: /*
463: * Walk from the tail to the head, free along the way.
464: */
465: for (; tmp2 != tmp; tmp--)
466: free(*tmp);
467: /*
468: * Now free the list itself.
469: */
470: free(tmp2);
471:
472: /*
473: * Free the input line buffer, if we have one.
474: */
475: if (inpline != NULL) {
476: free(inpline);
477: inpline = NULL;
478: }
479: }
480:
481: static void
1.13 deraadt 482: run(char **argv)
1.1 deraadt 483: {
484: pid_t pid;
1.14 millert 485: int fd;
486: char **avec;
1.1 deraadt 487:
1.14 millert 488: /*
489: * If the user wants to be notified of each command before it is
490: * executed, notify them. If they want the notification to be
491: * followed by a prompt, then prompt them.
492: */
493: if (tflag || pflag) {
1.1 deraadt 494: (void)fprintf(stderr, "%s", *argv);
1.14 millert 495: for (avec = argv + 1; *avec != NULL; ++avec)
496: (void)fprintf(stderr, " %s", *avec);
497: /*
498: * If the user has asked to be prompted, do so.
499: */
500: if (pflag)
501: /*
502: * If they asked not to exec, return without execution
503: * but if they asked to, go to the execution. If we
504: * could not open their tty, break the switch and drop
505: * back to -t behaviour.
506: */
507: switch (prompt()) {
508: case 0:
509: return;
510: case 1:
511: goto exec;
512: case 2:
513: break;
514: }
1.1 deraadt 515: (void)fprintf(stderr, "\n");
516: (void)fflush(stderr);
517: }
1.14 millert 518: exec:
1.20 millert 519: switch (pid = vfork()) {
1.1 deraadt 520: case -1:
521: err(1, "vfork");
522: case 0:
1.14 millert 523: if (oflag) {
1.17 tedu 524: if ((fd = open(_PATH_TTY, O_RDONLY)) == -1) {
525: warn("can't open /dev/tty");
526: _exit(1);
527: }
1.14 millert 528: } else {
529: fd = open(_PATH_DEVNULL, O_RDONLY);
530: }
531: if (fd > STDIN_FILENO) {
1.17 tedu 532: if (dup2(fd, STDIN_FILENO) != 0) {
533: warn("can't dup2 to stdin");
534: _exit(1);
535: }
1.16 millert 536: close(fd);
1.14 millert 537: }
1.1 deraadt 538: execvp(argv[0], argv);
1.24 deraadt 539: warn("%s", argv[0]);
1.19 millert 540: _exit(errno == ENOENT ? 127 : 126);
1.1 deraadt 541: }
1.14 millert 542: curprocs++;
543: waitchildren(*argv, 0);
544: }
1.1 deraadt 545:
1.14 millert 546: static void
547: waitchildren(const char *name, int waitall)
548: {
549: pid_t pid;
550: int status;
1.1 deraadt 551:
1.14 millert 552: while ((pid = waitpid(-1, &status, !waitall && curprocs < maxprocs ?
553: WNOHANG : 0)) > 0) {
554: curprocs--;
555: /*
556: * According to POSIX, we have to exit if the utility exits
557: * with a 255 status, or is interrupted by a signal.
558: * We are allowed to return any exit status between 1 and
559: * 125 in these cases, but we'll use 124 and 125, the same
560: * values used by GNU xargs.
561: */
562: if (WIFEXITED(status)) {
563: if (WEXITSTATUS(status) == 255) {
564: warnx("%s exited with status 255", name);
565: exit(124);
1.24 deraadt 566: } else if (WEXITSTATUS(status) == 127 ||
1.19 millert 567: WEXITSTATUS(status) == 126) {
568: exit(WEXITSTATUS(status));
1.14 millert 569: } else if (WEXITSTATUS(status) != 0) {
570: rval = 123;
571: }
572: } else if (WIFSIGNALED(status)) {
573: if (WTERMSIG(status) != SIGPIPE) {
574: if (WTERMSIG(status) < NSIG)
575: warnx("%s terminated by SIG%s", name,
576: sys_signame[WTERMSIG(status)]);
577: else
578: warnx("%s terminated by signal %d",
579: name, WTERMSIG(status));
580: }
581: exit(125);
1.6 deraadt 582: }
1.1 deraadt 583: }
1.14 millert 584: if (pid == -1 && errno != ECHILD)
585: err(1, "waitpid");
586: }
587:
588: /*
589: * Prompt the user about running a command.
590: */
591: static int
592: prompt(void)
593: {
594: regex_t cre;
595: size_t rsize;
596: int match;
597: char *response;
598: FILE *ttyfp;
599:
600: if ((ttyfp = fopen(_PATH_TTY, "r")) == NULL)
601: return (2); /* Indicate that the TTY failed to open. */
602: (void)fprintf(stderr, "?...");
603: (void)fflush(stderr);
604: if ((response = fgetln(ttyfp, &rsize)) == NULL ||
605: regcomp(&cre, nl_langinfo(YESEXPR), REG_BASIC) != 0) {
606: (void)fclose(ttyfp);
607: return (0);
608: }
1.24 deraadt 609: response[rsize - 1] = '\0';
1.14 millert 610: match = regexec(&cre, response, 0, NULL, 0);
611: (void)fclose(ttyfp);
612: regfree(&cre);
613: return (match == 0);
1.1 deraadt 614: }
615:
1.14 millert 616: static void
1.13 deraadt 617: usage(void)
1.1 deraadt 618: {
1.13 deraadt 619: fprintf(stderr,
1.22 jmc 620: "usage: xargs [-0oprt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]\n"
1.14 millert 621: " [-L number] [-n number [-x]] [-P maxprocs] [-s size]\n"
622: " [utility [argument ...]]\n");
1.1 deraadt 623: exit(1);
624: }