From 815b63fd3a630eb462e7ab9d8af09f19e129a5af Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 9 May 2017 21:04:11 -0400 Subject: Implement -D exec --- bfs.h | 10 ++++++---- exec.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- exec.h | 10 +++++++--- parse.c | 7 ++++++- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/bfs.h b/bfs.h index d3aa80e..7a41537 100644 --- a/bfs.h +++ b/bfs.h @@ -57,14 +57,16 @@ typedef bool eval_fn(const struct expr *expr, struct eval_state *state); * Various debugging flags. */ enum debug_flags { + /** Print executed command details. */ + DEBUG_EXEC = 1 << 0, /** Print optimization details. */ - DEBUG_OPT = 1 << 0, + DEBUG_OPT = 1 << 1, /** Print rate information. */ - DEBUG_RATES = 1 << 1, + DEBUG_RATES = 1 << 2, /** Trace all stat() calls. */ - DEBUG_STAT = 1 << 2, + DEBUG_STAT = 1 << 3, /** Print the parse tree. */ - DEBUG_TREE = 1 << 3, + DEBUG_TREE = 1 << 4, }; /** diff --git a/exec.c b/exec.c index e28b4fc..5f3a804 100644 --- a/exec.c +++ b/exec.c @@ -10,6 +10,7 @@ *********************************************************************/ #include "exec.h" +#include "bfs.h" #include "bftw.h" #include "color.h" #include "dstring.h" @@ -18,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +27,28 @@ #include #include +/** Print some debugging info. */ +static void bfs_exec_debug(const struct bfs_exec *execbuf, const char *format, ...) { + if (!(execbuf->flags & BFS_EXEC_DEBUG)) { + return; + } + + if (execbuf->flags & BFS_EXEC_CONFIRM) { + fputs("-ok", stderr); + } else { + fputs("-exec", stderr); + } + if (execbuf->flags & BFS_EXEC_CHDIR) { + fputs("dir", stderr); + } + fputs(": ", stderr); + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); +} + extern char **environ; /** Determine the size of a single argument, for comparison to arg_max. */ @@ -38,14 +62,17 @@ static size_t bfs_exec_arg_size(const char *arg) { /** Determine the maximum argv size. */ static size_t bfs_exec_arg_max(const struct bfs_exec *execbuf) { long arg_max = sysconf(_SC_ARG_MAX); + bfs_exec_debug(execbuf, "ARG_MAX: %ld according to sysconf()\n", arg_max); if (arg_max < 0) { arg_max = BFS_EXEC_ARG_MAX; + bfs_exec_debug(execbuf, "ARG_MAX: %ld assumed\n", arg_max); } // We have to share space with the environment variables for (char **envp = environ; *envp; ++envp) { arg_max -= bfs_exec_arg_size(*envp); } + bfs_exec_debug(execbuf, "ARG_MAX: %ld remaining after environment variables\n", arg_max); // Account for the non-placeholder arguments for (size_t i = 0; i < execbuf->placeholder; ++i) { @@ -54,9 +81,11 @@ static size_t bfs_exec_arg_max(const struct bfs_exec *execbuf) { for (size_t i = execbuf->placeholder + 1; i < execbuf->tmpl_argc; ++i) { arg_max -= bfs_exec_arg_size(execbuf->tmpl_argv[i]); } + bfs_exec_debug(execbuf, "ARG_MAX: %ld remaining after fixed arguments\n", arg_max); // POSIX recommends subtracting 2048, for some wiggle room arg_max -= 2048; + bfs_exec_debug(execbuf, "ARG_MAX: %ld remaining after headroom\n", arg_max); if (arg_max < 0) { arg_max = 0; @@ -64,10 +93,13 @@ static size_t bfs_exec_arg_max(const struct bfs_exec *execbuf) { arg_max = BFS_EXEC_ARG_MAX; } + bfs_exec_debug(execbuf, "ARG_MAX: %ld final value\n", arg_max); return arg_max; } -struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, CFILE *cerr) { +struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, const struct cmdline *cmdline) { + CFILE *cerr = cmdline->cerr; + struct bfs_exec *execbuf = malloc(sizeof(*execbuf)); if (!execbuf) { perror("malloc()"); @@ -86,6 +118,10 @@ struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, CFILE *c execbuf->wd_len = 0; execbuf->ret = 0; + if (cmdline->debug & DEBUG_EXEC) { + execbuf->flags |= BFS_EXEC_DEBUG; + } + size_t i; const char *arg; for (i = 1, arg = argv[i]; arg; arg = argv[++i]) { @@ -319,6 +355,8 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { } } + bfs_exec_debug(execbuf, "Executing '%s' ... [%zu arguments]\n", execbuf->argv[0], execbuf->argc - 1); + pid_t pid = fork(); if (pid < 0) { @@ -425,15 +463,15 @@ static int bfs_exec_flush(struct bfs_exec *execbuf) { /** Check if a flush is needed before a new file is processed. */ static bool bfs_exec_needs_flush(struct bfs_exec *execbuf, const struct BFTW *ftwbuf, const char *arg) { if (execbuf->flags & BFS_EXEC_CHDIR) { - if (ftwbuf->nameoff > execbuf->wd_len) { - return true; - } - if (execbuf->wd_path && strncmp(ftwbuf->path, execbuf->wd_path, execbuf->wd_len) != 0) { + if (ftwbuf->nameoff > execbuf->wd_len + || (execbuf->wd_path && strncmp(ftwbuf->path, execbuf->wd_path, execbuf->wd_len) != 0)) { + bfs_exec_debug(execbuf, "Changed directories, executing buffered command\n"); return true; } } if (execbuf->arg_size + bfs_exec_arg_size(arg) > execbuf->arg_max) { + bfs_exec_debug(execbuf, "Reached max command size, executing buffered command\n"); return true; } @@ -518,6 +556,7 @@ int bfs_exec(struct bfs_exec *execbuf, const struct BFTW *ftwbuf) { int bfs_exec_finish(struct bfs_exec *execbuf) { if (execbuf->flags & BFS_EXEC_MULTI) { + bfs_exec_debug(execbuf, "Finishing execution, executing buffered command\n"); if (bfs_exec_flush(execbuf) != 0) { execbuf->ret = -1; } diff --git a/exec.h b/exec.h index 498013a..d4a7154 100644 --- a/exec.h +++ b/exec.h @@ -15,6 +15,8 @@ #include "bftw.h" #include "color.h" +struct cmdline; + /** * Flags for the -exec actions. */ @@ -25,6 +27,8 @@ enum bfs_exec_flags { BFS_EXEC_CHDIR = 1 << 1, /** Pass multiple files at once to the command (-exec ... {} +). */ BFS_EXEC_MULTI = 1 << 2, + /** Print debugging information (-D exec). */ + BFS_EXEC_DEBUG = 1 << 3, }; /** @@ -72,11 +76,11 @@ struct bfs_exec { * The (bfs) command line argument to parse. * @param flags * Any flags for this exec action. - * @param cerr - * For error messages. + * @param cmdline + * The command line. * @return The parsed exec action, or NULL on failure. */ -struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, CFILE *cerr); +struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, const struct cmdline *cmdline); /** * Execute the command for a file. diff --git a/parse.c b/parse.c index 6be2e97..4a7fbe0 100644 --- a/parse.c +++ b/parse.c @@ -697,6 +697,8 @@ static struct expr *parse_debug(struct parser_state *state, int arg1, int arg2) state->just_info = true; return NULL; + } else if (strcmp(flag, "exec") == 0) { + cmdline->debug |= DEBUG_EXEC; } else if (strcmp(flag, "opt") == 0) { cmdline->debug |= DEBUG_OPT; } else if (strcmp(flag, "rates") == 0) { @@ -912,7 +914,7 @@ static struct expr *parse_empty(struct parser_state *state, int arg1, int arg2) * Parse -exec(dir)?/-ok(dir)?. */ static struct expr *parse_exec(struct parser_state *state, int flags, int arg2) { - struct bfs_exec *execbuf = parse_bfs_exec(state->argv, flags, state->cmdline->cerr); + struct bfs_exec *execbuf = parse_bfs_exec(state->argv, flags, state->cmdline); if (!execbuf) { return NULL; } @@ -2741,6 +2743,9 @@ void dump_cmdline(const struct cmdline *cmdline, bool verbose) { fprintf(stderr, "-O%d ", cmdline->optlevel); } + if (cmdline->debug & DEBUG_EXEC) { + fputs("-D exec ", stderr); + } if (cmdline->debug & DEBUG_OPT) { fputs("-D opt ", stderr); } -- cgit v1.2.3