summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-05-09 21:04:11 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-05-09 21:04:11 -0400
commit815b63fd3a630eb462e7ab9d8af09f19e129a5af (patch)
tree97eed9b70784e8e11d4b9c8630b7708be8dc3da7
parentc8c33b8c44751444729eda6a9fb7d4715928ea43 (diff)
downloadbfs-815b63fd3a630eb462e7ab9d8af09f19e129a5af.tar.xz
Implement -D exec
-rw-r--r--bfs.h10
-rw-r--r--exec.c49
-rw-r--r--exec.h10
-rw-r--r--parse.c7
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 <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -25,6 +27,28 @@
#include <sys/wait.h>
#include <unistd.h>
+/** 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);
}