From 2035073c76d7e7e1a80c8495c0d364699139aa46 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Wed, 16 Sep 2020 23:50:18 +0200
Subject: [PATCH] find: improve '-D exec' debug output

Previously, 'find -D exec' only gave helpful output right before the
invocation of complete_pending_execdirs, i.e., not for every child
execution of the -exec, -execdir, -ok and -okdir predicates.
Make the 'exec' debug output more useful and consistent.

* find/exec.c (launch): Output DebugExec diagnostics right before spawning
the child process, and after getting its exit status (unless we already
have regular error diagnotstic anyway, e.g. if the child has been
terminated by a signal).
* find/ftsfind.c (show_outstanding_execdirs): Remove.
(find): Remove invocation of the above function, and simplify.
* NEW: Mention the improvement.

Suggested by Philip Rowlands in https://sv.gnu.org/bugs/?59083
---
 NEWS           |  3 +++
 find/exec.c    | 23 ++++++++++++++++++++-
 find/ftsfind.c | 55 ++------------------------------------------------
 3 files changed, 27 insertions(+), 54 deletions(-)

diff --git a/NEWS b/NEWS
index 86198991..aa6083dc 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,9 @@ find -used works again.  This predicate was not working properly since adding
 the support for sub-second timestamp resolution for various predicates in
 FINDUTILS_4_3_3-1 back in 2007.
 
+#59083: 'find -D exec' now diagnoses all -exec, -execdir, -ok and -okdir runs
+including the call arguments and the exit code of the launched process.
+
 #58654: doc: clarify that 'find -perm +MODE' is unrelated to umask
 
 #58458: doc: improve section 'Hard links', especially fix the description
diff --git a/find/exec.c b/find/exec.c
index a656924d..5551de56 100644
--- a/find/exec.c
+++ b/find/exec.c
@@ -287,6 +287,19 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
   (void) ctl;			/* silence compiler warning */
   (void) argc;			/* silence compiler warning */
 
+  if (options.debug_options & DebugExec)
+    {
+      int i;
+      fprintf (stderr, "DebugExec: launching process (argc=%" PRIuMAX "):",
+               (uintmax_t) execp->state.cmd_argc - 1);
+      for (i=0; i<execp->state.cmd_argc -1; ++i)
+	{
+	  fprintf (stderr, " %s",
+	           safely_quote_err_filename (0, execp->state.cmd_argv[i]));
+	}
+      fprintf (stderr, "\n");
+    }
+
   /* Make sure output of command doesn't get mixed with find output. */
   fflush (stdout);
   fflush (stderr);
@@ -356,7 +369,15 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
       return 1;			/* OK */
     }
 
-  if (0 == WEXITSTATUS (execp->last_child_status))
+  int ex = WEXITSTATUS (execp->last_child_status);
+  if (options.debug_options & DebugExec)
+    {
+      fprintf (stderr,
+               "DebugExec: process (PID=%d) terminated with exit status: %d\n",
+               child_pid, ex);
+    }
+
+  if (0 == ex)
     {
       return 1;			/* OK */
     }
diff --git a/find/ftsfind.c b/find/ftsfind.c
index 783148c5..d855ac3a 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -264,53 +264,6 @@ symlink_loop (const char *name)
 }
 
 
-static void
-show_outstanding_execdirs (FILE *fp)
-{
-  if (options.debug_options & DebugExec)
-    {
-      bool seen = false;
-      struct predicate *p;
-      p = get_eval_tree ();
-      fprintf (fp, "Outstanding execdirs:");
-
-      while (p)
-	{
-	  const char *pfx;
-
-	  if (pred_is (p, pred_execdir))
-	    pfx = "-execdir";
-	  else if (pred_is (p, pred_okdir))
-	    pfx = "-okdir";
-	  else
-	    pfx = NULL;
-	  if (pfx)
-	    {
-	      size_t i;
-	      const struct exec_val *execp = &p->args.exec_vec;
-	      seen = true;
-
-	      fprintf (fp, "%s ", pfx);
-	      if (execp->multiple)
-		fprintf (fp, "multiple ");
-	      fprintf (fp, "%" PRIuMAX " args: ", (uintmax_t) execp->state.cmd_argc);
-	      for (i=0; i<execp->state.cmd_argc; ++i)
-		{
-		  fprintf (fp, "%s ", execp->state.cmd_argv[i]);
-		}
-	      fprintf (fp, "\n");
-	    }
-	  p = p->pred_next;
-	}
-      if (!seen)
-	fprintf (fp, " none\n");
-    }
-  else
-    {
-      /* No debug output is wanted. */
-    }
-}
-
 static void
 consider_visiting (FTS *p, FTSENT *ent)
 {
@@ -560,7 +513,7 @@ find (char *arg)
 
       while ( (errno=0, ent=fts_read (p)) != NULL )
 	{
-	  if (state.execdirs_outstanding)
+	  if (state.execdirs_outstanding && ((int)ent->fts_level != level))
 	    {
 	      /* If we changed level, perform any outstanding
 	       * execdirs.  If we see a sequence of directory entries
@@ -569,11 +522,7 @@ find (char *arg)
 	       * builds a command line for only 3 files at a time
 	       * (since fts descends into the directories).
 	       */
-	      if ((int)ent->fts_level != level)
-		{
-		  show_outstanding_execdirs (stderr);
-		  complete_pending_execdirs ();
-		}
+	      complete_pending_execdirs ();
 	    }
 	  level = (int)ent->fts_level;
 
-- 
2.28.0

