From 3b852d7d9ce6832f2aa9f6526d29a4ba1a80b370 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 30 Dec 2014 11:39:05 +0000 Subject: [PATCH] utils: Add xargs from ELKS --- Applications/util/Makefile | 1 + Applications/util/xargs.c | 254 +++++++++++++++++++++++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 Applications/util/xargs.c diff --git a/Applications/util/Makefile b/Applications/util/Makefile index 5cebabad..2614877c 100644 --- a/Applications/util/Makefile +++ b/Applications/util/Makefile @@ -89,6 +89,7 @@ SRCS = banner.c \ wc.c \ which.c \ whoami.c \ + xargs.c \ yes.c OBJS = $(SRCS:.c=.rel) diff --git a/Applications/util/xargs.c b/Applications/util/xargs.c new file mode 100644 index 00000000..e9b13199 --- /dev/null +++ b/Applications/util/xargs.c @@ -0,0 +1,254 @@ +/* + * xargs.c + * + * Copyright 2000 Alistair Riddoch + * ajr@ecs.soton.ac.uk + * + * This file may be distributed under the terms of the GNU General Public + * License v2, or at your option any later version. + */ + +/* + * This is a small version of xargs for use in the ELKS project. + * It is not fully functional, and may not be the most efficient + * implementation for larger systems. It minimises memory usage and + * code size. + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_ARGS 20 +#define MAX_IARGS 10 +#define MAX_CHARS 255 + +#define DEFAULT_CMD "/bin/echo" + +int max_args = MAX_ARGS; +int max_chars = MAX_CHARS; /* Not yet implemented */ + +char * progname; + +/* Command to run if none specified */ +char * default_cmd = DEFAULT_CMD; + +/* New arguments for programs */ +int nargc; +char * nargv[MAX_ARGS + MAX_IARGS + 2]; + +/* + * + * usage() + * + * Display usage information. + * + */ + +void usage(char ** argv) +{ + fprintf(stderr, "%s [-n max-args] [-s max-chars] [command [initial-arguments]]\n", argv[0]); + exit(1); +} + +/* + * + * do_args() + * + * Interpret command switches from the command line. + * + * int argc; As passed to main(). + * char ** argv; As passed to main(). + * + * RETURN Num of arguments interpreted. + * + */ + + +int do_args(int argc, char ** argv) +{ + int i = 1, j, k; + + while(i < argc && argv[i][0] == '-') { + k = 0; + for(j = 1; j < strlen(argv[i]); j++) { + switch (argv[i][j]) { + case 'n': + k++; + if ((i + k) < argc) { + max_args = atoi(argv[i+k]); + } + break; + case 's': + k++; + if ((i + k) < argc) { + max_chars = atoi(argv[i+k]); + } + break; + default: + usage(argv); + } + } + i += k; + i++; + } + if (max_args > MAX_ARGS) { + max_args = MAX_ARGS; + } + if (max_chars > MAX_CHARS) { + max_chars = MAX_CHARS; + } + return i; +} + +/* + * + * build_cmd() + * + * Build the initial portion of the argv array to be used to run + * commands from the command line arguments given for xargs. + * + * int argc; Number of arguments left. + * char ** argv; Pointer to the first item in main()'s argv for us. + * + */ + +void build_cmd(int argc, char ** argv) +{ + int i; + + if (argc > (MAX_IARGS + MAX_ARGS - max_args)) { + fprintf(stderr, "%s: Too many initial arguments.\n", progname); + exit(1); + } + for(i = 0; i < argc; i++) { + nargv[i] = argv[i]; + } + nargc += argc; +} + +#define BSIZE 64 +#define out_of_mem() { perror("malloc"); exit(1); } + +/* + * next_token() + * + * Read standard in and get the next argument. + * Returns NULL on end of file. + * + */ + +char * next_token(void) +{ + int size = BSIZE; + int tail = 0; + char * buf = malloc(BSIZE); + + if (buf == NULL) { + out_of_mem(); + } + for(;;) { + int inp = fgetc(stdin); + switch (inp) { + case EOF: + if (tail != 0) { + buf[tail] = '\0'; + } else { + free(buf); + buf = NULL; + } + return buf; + break; + case ' ': + case '\t': + case '\n': + if (tail != 0) { + buf[tail] = '\0'; + return buf; + } + break; + default: + buf[tail++] = inp; + break; + } + if (tail > size) { + size += BSIZE; + buf = realloc(buf, size); + if (buf == NULL) { + out_of_mem(); + } + } + + } +} + +/* + * + * run() + * + * Fork, exec and wait for the commant to complete. + * + * Parameters are as for execvp. + * + * We use vfork as this is a good saving under elks. + * + */ + +void run(char * argv0, char ** argv) +{ + int pid; + + pid = fork(); + switch (pid) { + case -1: + perror("fork"); + exit(1); + break; + case 0: + break; + default: + wait(NULL); + return; + } + execvp(argv0, argv); + perror("argv0"); + exit(1); +} + +int main(int argc, char ** argv) +{ + int num_args; + int new_argc; + char * tok = NULL; + + progname = argv[0]; + num_args = do_args(argc, argv); + + if (num_args >= argc) { + build_cmd(1, &default_cmd); + } else { + build_cmd(argc - num_args, &argv[num_args]); + } + + do { + int i; + + new_argc = nargc; + while(new_argc < (nargc + max_args) && + (tok = next_token()) != NULL) { + nargv[new_argc++] = tok; + } + nargv[new_argc] = NULL; + if (nargc != new_argc) { + run(nargv[0], nargv); + } + for(i = nargc; i < new_argc; i++) { + free(nargv[i]); + } + } while (tok != NULL); + + exit(0); +} -- 2.34.1