Passing Arguments to su-Provided Shell in Bash

bashoptionsshellsu

man su says:

You can use the -- argument to separate su options from the arguments
supplied to the shell.

man bash says:

--        A  --  signals  the  end of options and disables further option
          processing.  Any arguments after the -- are treated as filenames
          and arguments.  An argument of - is equivalent to --.

Well then, let's see:

[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3                                                       
2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3                                                        
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3                                                           
1 2 3

What I expected (output of the second command differs):

[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3                                                       
1 2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3                                                        
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3                                                           
1 2 3

Probably not much of an issue. But what's happening there? The second and the third variants seem like the way to go, but one of them doesn't work. The fourth one seems unreliable, - can be treated as su's option.

Best Answer

What is happening is that the first argument you supply to the shell is the $0 parameter, (usually this would be the name of the shell). It is not included when you do echo $* since $* is every argument apart from $0.

Example:

# su - graeme -c 'echo "\$0 - $0"; echo "\$* - $*"' -- sh 1 2 3
$0 - sh
$* - 1 2 3

Update

Doing the following command:

strace -f su graeme -c 'echo $0; echo "$*"' -- -- 1 2 3

yields the strace line:

[pid  9609] execve("/bin/bash", ["bash", "-c", "echo $0; echo \"$*\"", "1", "2", "3"], [/* 27 vars */] <unfinished ...>

So somehow it seems that in this case su is gobbling up the extra -- without passing it to bash, possibly due to a bug (or at least undocumented behaviour). It won't however eat up any more than two of the -- arguments:

# su graeme -c 'echo $0; echo "$*"' -- -- -- 1 2 3
--
1 2 3
Related Question