be1fada78ba458c79ac1476fe577bf114345e5e7
[oweals/busybox.git] / findutils / xargs.c
1 /* minix xargs - Make and execute commands           
2  * Author: Ian Nicholls:  1 Mar 90 */
3
4 /*
5  * xargs  - Accept words from stdin until, combined with the arguments
6  *          given on the command line, just fit into the command line limit.
7  *          Then, execute the result.
8  *              e.g.    ls | xargs compress
9  *                      find . -name '*.s' -print | xargs ar qv libc.a
10  *
11  * flags: -t            Print the command just before it is run
12  *        -l len        Use len as maximum line length (default 490, max 1023)
13  *        -e ending     Append ending to the command before executing it.
14  *
15  * Exits with:  0  No errors.
16  *              1  If any system(3) call returns a nonzero status.
17  *              2  Usage error
18  *              3  Line length too short to contain some single argument.
19  *
20  * Examples:    xargs ar qv libc.a < liborder           # Create a new libc.a
21  *              find . -name '*.s' -print | xargs rm    # Remove all .s files
22  *              find . -type f ! -name '*.Z' \          # Compress old files.
23  *                     -atime +60 -print  | xargs compress -v
24  *
25  * Bugs:  If the command contains unquoted wildflags, then the system(3) call
26  *              call may expand this to larger than the maximum line size.
27  *        The command is not executed if nothing was read from stdin.
28  *        xargs may give up too easily when the command returns nonzero.
29  */
30 #define USAGE "usage: xargs [-t] [-l len] [-e endargs] command [args...]\n"
31
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <getopt.h>
37
38 #ifndef MAX_ARGLINE
39 # define MAX_ARGLINE 1023
40 #endif
41 #ifndef min
42 # define min(a,b) ((a) < (b) ? (a) : (b))
43 #endif
44
45 char outlin[MAX_ARGLINE];
46 char inlin[MAX_ARGLINE];
47 char startlin[MAX_ARGLINE];
48 char *ending = NULL;
49 char traceflag = 0;
50
51 int xargs_main(int ac, char **av)
52 {
53    int outlen, inlen, startlen, endlen=0, i;
54    char errflg = 0;
55    int maxlin = MAX_ARGLINE;
56
57    while ((i = getopt(ac, av, "tl:e:")) != EOF)
58        switch (i) {
59            case 't': traceflag = 1;       break;
60            case 'l': maxlin = min(MAX_ARGLINE, atoi(optarg)); break;
61            case 'e': ending = optarg;     break;
62            case '?': errflg++;            break;
63        }
64    if (errflg)  {
65        fprintf(stderr, USAGE);
66        exit(2);
67    }
68
69    startlin[0] = 0;
70    if (optind == ac) {
71        strcat(startlin, "echo ");
72    }
73    else for ( ; optind < ac; optind++) {
74        strcat(startlin, av[optind]);
75        strcat(startlin, " ");
76    }
77    startlen = strlen(startlin);
78    if (ending) endlen = strlen(ending);
79    maxlin = maxlin - 1 - endlen;        /* Pre-compute */
80
81    strcpy(outlin, startlin);
82    outlen = startlen;
83
84    while (gets(inlin) != NULL) {
85        inlen = strlen(inlin);
86        if (maxlin <= (outlen + inlen)) {
87            if (outlen == startlen) {
88                fprintf(stderr, "%s: Line length too short to process '%s'\n",
89                        av[0], inlin);
90                exit(3);
91            }
92            if (ending) strcat(outlin, ending);
93            if (traceflag) fputs(outlin,stderr);
94            errno = 0;
95            if (0 != system(outlin)) {
96                if (errno != 0) perror("xargs");
97                exit(1);
98            }
99            strcpy(outlin, startlin);
100            outlen = startlen;
101        }
102        strcat(outlin, inlin);
103        strcat(outlin, " ");
104        outlen = outlen + inlen + 1;
105    }
106    if (outlen != startlen) {
107        if (ending) strcat(outlin, ending);
108        if (traceflag) fputs(outlin,stderr);
109        errno = 0;
110        if (0 != system(outlin)) {
111            if (errno != 0) perror("xargs");
112            exit(1);
113        }
114    }    
115    return 0;
116 }