--- Makefile | 1 + xargs.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 xargs.c diff --git a/Makefile b/Makefile index 2a72a1c..81dfaf6 100644 --- a/Makefile +++ b/Makefile _AT_@ -93,6 +93,7 @@ SRC = \ stat.c \ wc.c \ who.c \ + xargs.c \ yes.c OBJ = $(SRC:.c=.o) $(LIB) diff --git a/xargs.c b/xargs.c new file mode 100644 index 0000000..72159ef --- /dev/null +++ b/xargs.c _AT_@ -0,0 +1,213 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/wait.h> +#include <unistd.h> +#include "text.h" +#include "util.h" + +static int inputc(void); +static void deinputc(int); +static void eatspace(void); +static char *poparg(void); +static int parsesquote(void); +static int parsedquote(void); +static char *poparg(void); +static void pusharg(char *); +static int runcmd(void); + +static void +usage(void) +{ + eprintf("usage: %s [-r] [cmd [arg...]]", argv0); +} + +static char **cmd; +static char argb[BUFSIZ]; +static size_t argbpos; +static int rflag = 0; + +int +main(int argc, char *argv[]) +{ + char *arg; + int i = 0; + + ARGBEGIN { + case 'r': + rflag = 1; + break; + default: + usage(); + } ARGEND; + + cmd = malloc(sysconf(_SC_ARG_MAX) * sizeof(*cmd)); + if (!cmd) + eprintf("malloc:"); + + do { + if (argc > 0) + for (i = 0; i < argc; i++) + cmd[i] = strdup(argv[i]); + else + cmd[i++] = strdup("/bin/echo"); + while ((arg = poparg())) { + if (i < sysconf(_SC_ARG_MAX) - 1) { + cmd[i++] = strdup(arg); + } else { + pusharg(arg); + break; + } + } + cmd[i] = NULL; + runcmd(); + for (; i >= 0; i--) + free(cmd[i]); + } while (arg); + + free(cmd); + return 0; +} + +static int +inputc(void) +{ + int ch; + + ch = getc(stdin); + if (ch == EOF && ferror(stdin)) + eprintf("stdin: read error:"); + return ch; +} + +static void +deinputc(int ch) +{ + ungetc(ch, stdin); +} + +static void +eatspace(void) +{ + int ch; + + while ((ch = inputc()) != EOF) { + switch (ch) { + case ' ': case '\t': case '\n': + break; + default: + deinputc(ch); + return; + } + } +} + +static int +parsesquote(void) +{ + int ch; + int ok = -1; + + while ((ch = inputc()) != EOF) { + switch (ch) { + case '\'': + argb[argbpos] = '\0'; + ok = 0; + break; + default: + if (ch != '\n') + argb[argbpos++] = ch; + break; + } + } + return ok; +} + +static int +parsedquote(void) +{ + int ch; + int ok = -1; + + while ((ch = inputc()) != EOF) { + switch (ch) { + case '\"': + argb[argbpos] = '\0'; + ok = 0; + break; + default: + if (ch != '\n') + argb[argbpos++] = ch; + break; + } + } + return ok; +} + +static char * +poparg(void) +{ + int ch; + int escape = 0; + + argbpos = 0; + eatspace(); + while ((ch = inputc()) != EOF) { + switch (ch) { + case ' ': case '\t': case '\n': + if (escape == 1) { + escape = !escape; + if (ch != '\n') { + argb[argbpos++] = ch; + break; + } + } + argb[argbpos] = '\0'; + deinputc(ch); + return argb; + case '\'': + if (parsesquote() == -1) + enprintf(EXIT_FAILURE, "unterminated quote\n"); + break; + case '\"': + if (parsedquote() == -1) + enprintf(EXIT_FAILURE, "unterminated quote\n"); + break; + case '\\': + escape = !escape; + break; + default: + argb[argbpos++] = ch; + break; + } + } + if (argbpos > 0) { + argb[argbpos] = '\0'; + return argb; + } + return NULL; +} + +static void +pusharg(char *arg) +{ + char *p; + + for (p = &arg[strlen(arg) - 1]; p >= arg; p--) + deinputc(*p); +} + +static int +runcmd(void) +{ + pid_t pid; + + pid = fork(); + if (pid < 0) + eprintf("fork:"); + if (pid == 0) + execvp(*cmd, cmd); + wait(NULL); + return 0; +} -- 1.8.4.5 --k1lZvvs/B4yU6o8G--Received on Mon Sep 17 2001 - 00:00:00 CEST
This archive was generated by hypermail 2.3.0 : Fri Jan 03 2014 - 13:12:03 CET