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