diff --git a/TODO b/TODO index b364175..eb123b1 100644 --- a/TODO +++ b/TODO @@ -54,8 +54,7 @@ Modutils (linux only): Findutils: grep find - *xargs (stdin) - + *xargs (-r flag) Shell: rc - run command (1 2 3 ~ | <> <<>> & * " parsing) (sig handler) diff --git a/config.h b/config.h index bc5f5e0..2053327 100644 --- a/config.h +++ b/config.h @@ -10,7 +10,7 @@ /* format for printf (head) */ #define HEAD_FMT "==> %s <==\n" -/* block size (du)*/ +/* block size (du) */ #define BLK_SIZE 512 /* mount config */ @@ -29,8 +29,11 @@ /* RunComm prompt */ #define RC_PS "> " -/* Args count (xargs) */ -#define NARGS 10000 +/* Max args (xargs) */ +#define NARGS 1024 +#define ARG_SIZE 1024 + +/* Default cmd (xargs) */ #define ECHO_CMD "echo" /* Options: To disable, comment line */ diff --git a/findutils/xargs.c b/findutils/xargs.c index a169e9d..97d17de 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -3,34 +3,81 @@ #include #include #include +#include #include #include "config.h" -unsigned int t_flag; +int t_flag; +int n_flag; +int r_flag; + char *cmd[NARGS + 1]; +int args; -void clear_cmd(int count) { - if (count < 1) - return; +void clear_cmd(void) { + for (int i = 0; i < args; i++) + if (cmd[i] != NULL) + free(cmd[i]); - for (int i = 0; i < count; i++) - free(cmd[i]); + args = 0; } -char *estrdup(const char *arg, int i) { - char *val = strdup(arg); - if (!val) { - clear_cmd(i - 1); - fprintf(stderr, "xargs: %s\n", strerror(errno)); - return NULL; +int add_arg(const char *str) { + if (args >= NARGS) + return 1; + + else if (n_flag > 0 && args >= n_flag) + return 1; + + cmd[args] = strdup(str); + args++; + + return 0; +} + +int stdin_read(void) { + char arg[ARG_SIZE + 1]; + + /* Word start */ + char *p = arg; + + int run = 1; + int c = 0; + while ((c = getchar()) != EOF && run) { + switch (c) { + case '\t': + case '\n': + case ' ': + *p = '\0'; + p = arg; + + if (add_arg(arg)) + run = 0; + + break; + + default: + *p = c; + if (p + 1 == arg + sizeof(arg)) + run = 0; + + else + p++; + + break; + } } - return val; + + if (getchar() == EOF) + return 1; + + return 0; } -int run(int count) { +int run(void) { if (t_flag) { - for (int i = 0; i < count; i++) + for (int i = 0; i < args; i++) fprintf(stderr, "%s ", cmd[i]); fputc('\n', stderr); @@ -38,7 +85,7 @@ int run(int count) { pid_t pid; if ((pid = fork()) == 0) { - execvp(*cmd, cmd); + execvp(cmd[0], cmd); fprintf(stderr, "xargs: %s\n", strerror(errno)); exit(1); } @@ -50,14 +97,27 @@ int run(int count) { int main(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "t")) != -1) { + while ((opt = getopt(argc, argv, "tn:r")) != -1) { switch (opt) { case 't': t_flag = 1; break; + case 'n': + n_flag = atoi(optarg); + if (n_flag < 1) { + fprintf(stderr, "xargs: n cant be < 0\n"); + return 1; + } + + break; + + case 'r': + r_flag = 1; + break; + default: - printf("xargs [cmd] [arg1] [arg2]\n\t[-t Print the command on stderr before execution]\n"); + printf("xargs [cmd [arg1] [arg2...]]\n\t[-t Print the command]\n\t[-n Pass no more than N args]\n\t[TODO -r Don't run command if input is empty]\n"); return 0; } } @@ -65,22 +125,39 @@ int main(int argc, char **argv) { argv += optind; argc -= optind; - /* Argv */ - int i = 0; - if (argc) { - for (i = 0; i < argc; i++) - if (i < NARGS) - cmd[i] = estrdup(argv[i], i); + int ret = 0; + while (1) { + /* Arg */ + if (argc) { + for (int i = 0; i < argc; i++) + if (add_arg(argv[i])) + break; + } + + else + add_arg(ECHO_CMD); + + /* Stdin */ + int stdin_stat = stdin_read(); + + /* Check NULL */ + for (int i = 0; i < args; i++) { + if (cmd[i] == NULL) { + fprintf(stderr, "xargs: strdup failed\n"); + clear_cmd(); + return 1; + } + } + + /* Run */ + if (run()) + ret = 1; + + /* Clear */ + clear_cmd(); + if (stdin_stat) + break; } - else { - cmd[0] = estrdup(ECHO_CMD, 0); - i++; - } - - /* Stdin */ - - int ret = run(i); - clear_cmd(i); return ret; }