[PATCH] cli: try to run external notmuch- prefixed commands as subcommands

Subject: [PATCH] cli: try to run external notmuch- prefixed commands as subcommands

Date: Sat, 22 Oct 2016 15:50:05 +0300

To: notmuch@notmuchmail.org

Cc:

From: Jani Nikula


If the given subcommand is not known to notmuch, try to execute
external notmuch-<subcommand> instead. This allows users to have their
own notmuch related tools be run via the notmuch command, not unlike
git does. Also notmuch-emacs-mua will be executable via 'notmuch
emacs-mua'.

By design, this does not allow notmuch's own subcommands to be
overriden using external commands.

---

Whether internal subcommands can be overridden or not is up to debate,
can be consider either a bug or a feature depending on how you look at
it.
---
 notmuch.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index 38b73c1d2acc..b9c320329dd5 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -363,6 +363,39 @@ notmuch_command (notmuch_config_t *config,
     return EXIT_SUCCESS;
 }
 
+/*
+ * Try to run subcommand in argv[0] as notmuch- prefixed external
+ * command. argv must be NULL terminated (argv passed to main always
+ * is).
+ *
+ * Does not return if the external command is found and
+ * executed. Return TRUE if external command is not found. Return
+ * FALSE on errors.
+ */
+static notmuch_bool_t try_external_command(char *argv[])
+{
+    char *old_argv0 = argv[0];
+    notmuch_bool_t ret = TRUE;
+
+    argv[0] = talloc_asprintf (NULL, "notmuch-%s", old_argv0);
+
+    /*
+     * This will only return on errors. Not finding an external
+     * command (ENOENT) is not an error from our perspective.
+     */
+    execvp (argv[0], argv);
+    if (errno != ENOENT) {
+	fprintf (stderr, "Error: Running external command '%s' failed: %s\n",
+		 argv[0], strerror(errno));
+	ret = FALSE;
+    }
+
+    talloc_free (argv[0]);
+    argv[0] = old_argv0;
+
+    return ret;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -406,8 +439,10 @@ main (int argc, char *argv[])
 
     command = find_command (command_name);
     if (!command) {
-	fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
-		 command_name);
+	/* This won't return if the external command is found. */
+	if (try_external_command(argv + opt_index))
+	    fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
+		     command_name);
 	ret = EXIT_FAILURE;
 	goto DONE;
     }
-- 
2.1.4


Thread: