diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | xe.1 | 8 | ||||
-rw-r--r-- | xe.c | 73 |
3 files changed, 46 insertions, 39 deletions
diff --git a/README.md b/README.md index 55e2d88..84ec599 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Over xargs: * No weird parsing, arguments are seperated linewise or by NUL byte. * Can also take arguments from command-line. * No shell involved unless `-s` is used. +* `{}` replacing possible with multiple arguments. Over apply: * Parallel mode. @@ -31,7 +32,8 @@ Over apply: * `-k`: keep going: don't stop when a command failed to execute. * `-n`: don't run the commands, just print them. * `-v`: print commands to standard error before running them. -* `-I`: replace occurences of *arg* with the argument (default: `{}`). +* `-I`: replace occurences of *arg* with the argument(s) (default: `{}`). + Use an empty *arg* to disable the replace function. * `-N`: pass upto *maxargs* arguments to each COMMAND (default: 1). `-N0` will pass as many arguments as possible. * `-j`: run up to *maxjobs* processes concurrently. diff --git a/xe.1 b/xe.1 index 2ebfc67..86c07c0 100644 --- a/xe.1 +++ b/xe.1 @@ -81,9 +81,15 @@ Verbose: print commands to standard error before running them. .It Fl I Ar arg Replace occurences of .Ar arg -in the command with the argument. (default: .Cm {} ) +in the command with the argument(s). +Pass an empty +.Ar arg +to disable the replace function. +Contrary to +.Xr xargs 1 +this also works when multiple arguments are to be inserted. .It Fl N Ar maxargs Pass up to .Ar maxargs diff --git a/xe.c b/xe.c index bd781a3..c134e4d 100644 --- a/xe.c +++ b/xe.c @@ -33,7 +33,6 @@ static long iterations = 0; static FILE *traceout; static size_t argmax; -static int push_overflowed; static char *buf; static size_t buflen; @@ -42,6 +41,7 @@ static size_t bufcap; static char **args; static size_t argslen; static size_t argscap; +static size_t argsresv; static char **inargs; @@ -157,10 +157,8 @@ pusharg(const char *a) { size_t l = strlen(a) + 1; // including nul - if (buflen >= argmax - l || argslen + 1 >= argscap) { - push_overflowed = 1; + if (buflen >= argmax - l - argsresv || argslen + 1 >= argscap) return 0; - } if (buflen + l > bufcap) { while (buflen + l > bufcap) @@ -220,11 +218,18 @@ run() return 0; } +void +toolong() +{ + fprintf(stderr, "xe: fixed argument list too long\n"); + exit(1); +} + int main(int argc, char *argv[], char *envp[]) { char c; - int i, cmdend; + int i, j, cmdend; char *arg; bufcap = 4096; @@ -307,41 +312,35 @@ main(int argc, char *argv[], char *envp[]) pusharg("%s\\n"); } - if (maxatonce == 1) { - // substitute {} - int substituted = 0; - for (i = optind; i < cmdend; i++) { - if (strcmp(argv[i], replace) == 0) { - pusharg(arg); - substituted = 1; - } else { - pusharg(argv[i]); - } - } - if (!substituted) - pusharg(arg); - } else { - // just append to cmd - for (i = optind; i < cmdend; i++) - pusharg(argv[i]); - pusharg(arg); - if (!push_overflowed) { - for (i = 0; maxatonce < 1 || i < maxatonce - 1; i++) { - arg = getarg(); - if (!arg) - break; - if (!pusharg(arg)) { - run(); - goto keeparg; - } - } - } + for (i = optind; i < cmdend; i++) { + if (*replace && strcmp(argv[i], replace) == 0) + break; + if (!pusharg(argv[i])) + toolong(); } - if (push_overflowed) { - fprintf(stderr, "xe: fixed argument list too long\n"); - exit(1); + if (!pusharg(arg)) + toolong(); + arg = getarg(); + i++; + + // reserve space for final arguments + for (argsresv = 0, j = i; j < cmdend; j++) + argsresv += 1 + strlen(argv[j]); + + // fill with up to maxatonce arguments + for (j = 0; maxatonce < 1 || j < maxatonce-1; j++) { + if (!arg) + break; + if (!pusharg(arg)) + break; + arg = getarg(); } + + for (argsresv = 0, j = i; j < cmdend; j++) + if (!pusharg(argv[i])) + toolong(); + run(); } |