git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [BUG] [PATCH]: run-command.c

From
Jeff King <peff@peff.net>
Date
Oct 21, 2016, 09:00 UTC
Message-ID
<20161021090029.glr5u6gwrxluavir@sigill.intra.peff.net>
In-Reply-To
<20161021055013.GA31554@dimstar.local.net>
On Fri, Oct 21, 2016 at 04:50:13PM +1100, Duncan Roe wrote:
Show 16 quoted lines
> For example, if .git/config has this alias (the sleep is to leave time to
> examine output from ps, &c.):
> 
> [alias]
> 	tryme = "!echo $PWD;sleep 600"
>
> [...]
> 16:42:06$ ps axf|grep -A2 trym[e]
>  2599 pts/4    S+     0:00      \_ git tryme
>  2601 pts/4    S+     0:00          \_ /bin/sh -c echo $PWD;sleep 600 echo $PWD;sleep 600
>  2602 pts/4    S+     0:00              \_ sleep 600
> 16:42:45$ cat /proc/2601/cmdline | xargs -0 -n1 echo
> /bin/sh
> -c
> echo $PWD;sleep 600
> echo $PWD;sleep 600

This duplicated argument is expected and normal. The arguments after "-c whatever" become positional parameters $0, $1, etc. The actual script arguments start at "$1", and "$0" is typically the "script name". So you have to stick some placeholder value in the "$0" slot, so that the sub-script can find the actual arguments. E.g., try:

  sh -c '
    for i in "$@"; do
      echo "got $i"
    done
  ' one two three
it will print only:
  got two
  got three
But if you stick a placeholder there, it works:
  sh -c '
    for i in "$@"; do
      echo "got $i"
    done
  ' placeholder one two three

The value of the placeholder does not matter to the shell. But it is accessible to the script inside via $0:

  sh -c '
    echo "\$0 = $0"
    echo "\$1 = $1"
    echo "\$2 = $2"
    echo "\$3 = $3"
  ' placeholder one two three

Since our script does not have a filename, we just stick the script contents there (which is really just a convention, and one I doubt anybody is really relying on, but there's no point in breaking it now).

Show 12 quoted lines
> --- a/run-command.c
> +++ b/run-command.c
> @@ -182,8 +182,8 @@ static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
>  		else
>  			argv_array_pushf(out, "%s \"$@\"", argv[0]);
>  	}
> -
> -	argv_array_pushv(out, argv);
> +	else
> +		argv_array_pushv(out, argv);
>  	return out->argv;
>  }

Try running "make test" with this. Lots of things break, because we are not sending the positional parameters to the shell script at all.

If we just cared about the positional parmeters, we _could_ do something like:

  if (argv[0]) {
	argv_array_push(out, "sh");
	argv_array_pushv(out, argv + 1);
  }

That would omit "$0" entirely when we have no positional parameters (and the shell generally fills in "sh" there itself), and provide a dummy "sh" value when we need to use it as a placeholder.

But again, there's no real value in breaking the existing convention.
-Peff
Previous: Duncan RoeNext: Duncan Roe
Message 2 of 4 in “: run-command.c”
  1. Duncan RoeOct 21, 2016
  2. Jeff KingOct 21, 2016
  3. Duncan RoeOct 21, 2016
  4. Junio C HamanoOct 21, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.