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