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