--- Makefile | 1 + xargs.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 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..4dd858d --- /dev/null +++ b/xargs.c _AT_@ -0,0 +1,238 @@ +/* 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 fillbuf(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; +static size_t argbsz = 1; +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:"); + + argb = malloc(argbsz); + if (!argb) + 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; + if (i == 1 && rflag == 1); else runcmd(); + for (; i >= 0; i--) + free(cmd[i]); + } while (arg); + + free(argb); + 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 +fillbuf(int ch) +{ + if (argbpos >= argbsz) { + argbsz *= 2; + argb = realloc(argb, argbsz); + if (!argb) + eprintf("realloc:"); + } + argb[argbpos] = ch; +} + +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; + + while ((ch = inputc()) != EOF) { + switch (ch) { + case '\'': + fillbuf('\0'); + return 0; + default: + if (ch != '\n') { + fillbuf(ch); + argbpos++; + } + break; + } + } + return -1; +} + +static int +parsedquote(void) +{ + int ch; + + while ((ch = inputc()) != EOF) { + switch (ch) { + case '\"': + fillbuf('\0'); + return 0; + default: + if (ch != '\n') { + fillbuf(ch); + argbpos++; + } + break; + } + } + return -1; +} + +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') { + fillbuf(ch); + argbpos++; + break; + } + } + fillbuf('\0'); + deinputc(ch); + return argb; + case '\'': + if (parsesquote() == -1) + enprintf(EXIT_FAILURE, + "unterminated single quote\n"); + break; + case '\"': + if (parsedquote() == -1) + enprintf(EXIT_FAILURE, + "unterminated double quote\n"); + break; + case '\\': + escape = !escape; + break; + default: + fillbuf(ch); + argbpos++; + break; + } + } + if (argbpos > 0) { + fillbuf('\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); + eprintf("execvp %s:", *cmd); + } + wait(NULL); + return 0; +} -- 1.8.4.5 --envbJBWh7q8WU6mo--Received on Mon Sep 17 2001 - 00:00:00 CEST
This archive was generated by hypermail 2.3.0 : Fri Jan 03 2014 - 15:12:03 CET