Eric Blake wrote:
> Instead of using -- to force sh to realize the command being passed is
> intended to be a script to run (even if it starts with - or +), it is
> also possible to prepend a space.

Indeed, that it simpler than testing whether the command starts with - or +.

> I'm thinking of trying the alternative of not injecting "--" after
> all, but instead munging the given argument to supply a leading space.
> But that we need a new version of your patch.  Do you want to try and
> rework it along those lines, or should I make time for that?

Find attached a proposed patch. Tested on FreeBSD 13.1 and AIX 7.2; with
it, all m4 tests pass.

Bruno

>From e09b3ff04cbfce7073de5c7fd3812ffe9c48bac3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 14 Jan 2023 20:41:15 +0100
Subject: [PATCH] syscmd: Make it work again for most commands on FreeBSD and
 AIX.

Regression from 2021-11-19. Fix proposed by Eric Blake.

* src/builtin.c (m4_syscmd): On Unix, prepend a space to the command before
executing it.
(m4_esyscmd): Likewise.
---
 src/builtin.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/src/builtin.c b/src/builtin.c
index c7349596..38019f10 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -945,10 +945,10 @@ static void
 m4_syscmd (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
 {
   const char *cmd = ARG (1);
+  char *xcmd = NULL;
   int status;
   int sig_status;
-  int slot = 3;
-  const char *prog_args[5] = { "sh", "-c", "--" };
+  const char *prog_args[4] = { "sh", "-c" };
   if (bad_argc (argv[0], argc, 2, 2) || !*cmd)
     {
       /* The empty command is successful.  */
@@ -962,10 +962,20 @@ m4_syscmd (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     {
       prog_args[0] = "cmd";
       prog_args[1] = "/c";
-      slot = 2;
+      prog_args[2] = cmd;
     }
+  else
 #endif
-  prog_args[slot] = cmd;
+    {
+      /* If cmd starts with '-' or '+', 'sh -c "$cmd"' is not guaranteed to
+         work.  If we could assume a POSIX compliant SYSCMD_SHELL, we could use
+         'sh -c -- "$cmd"'.  But it does not work with /bin/sh on FreeBSD 13
+         and AIX 7, and on these platforms 'bash' is not guaranteed to be
+         installed.  Therefore use 'sh -c " $cmd"' instead.  */
+      xcmd = xasprintf (" %s", cmd);
+      prog_args[2] = xcmd;
+    }
+  prog_args[3] = NULL;
   errno = 0;
   status = execute (ARG (0), SYSCMD_SHELL, prog_args, NULL, false,
                     false, false, false, true, false, &sig_status);
@@ -980,14 +990,15 @@ m4_syscmd (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
         M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
       sysval = status;
     }
+  free (xcmd);
 }
 
 static void
 m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
 {
   const char *cmd = ARG (1);
-  int slot = 3;
-  const char *prog_args[5] = { "sh", "-c", "--" };
+  char *xcmd = NULL;
+  const char *prog_args[4] = { "sh", "-c" };
   pid_t child;
   int fd;
   FILE *pin;
@@ -1007,10 +1018,20 @@ m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
     {
       prog_args[0] = "cmd";
       prog_args[1] = "/c";
-      slot = 2;
+      prog_args[2] = cmd;
     }
+  else
 #endif
-  prog_args[slot] = cmd;
+    {
+      /* If cmd starts with '-' or '+', 'sh -c "$cmd"' is not guaranteed to
+         work.  If we could assume a POSIX compliant SYSCMD_SHELL, we could use
+         'sh -c -- "$cmd"'.  But it does not work with /bin/sh on FreeBSD 13
+         and AIX 7, and on these platforms 'bash' is not guaranteed to be
+         installed.  Therefore use 'sh -c " $cmd"' instead.  */
+      xcmd = xasprintf (" %s", cmd);
+      prog_args[2] = xcmd;
+    }
+  prog_args[3] = NULL;
   errno = 0;
   child = create_pipe_in (ARG (0), SYSCMD_SHELL, prog_args, NULL,
                           NULL, false, true, false, &fd);
@@ -1067,6 +1088,7 @@ m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
         M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
       sysval = status;
     }
+  free (xcmd);
 }
 
 static void
-- 
2.34.1

Reply via email to