Re: 'exec -a' and $0 substitution

2023-01-26 Thread Sergei Trofimovich
On Thu, 26 Jan 2023 00:35:27 -0500
Lawrence Velázquez  wrote:

> On Wed, Jan 25, 2023, at 6:37 PM, Sergei Trofimovich wrote:
> > I fear it's a side-effect of the way 'bash' gets executed via shebang by
> > kernel. But maybe not? Somehow direct script execution still manages to
> > preserve script's name. Is it an intended behaviour that could not be
> > easily changed? Or it's a bug?  
> 
> It's not a bug.

Thank you! That will make generic wrapping a bit more involved for us.

> https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-0
> 
>   0
>   ($0)  Expands to the name of the shell or shell
>   script.  This is set at shell initialization.  If
>   Bash is invoked with a file of commands (see Shell
>   Scripts), $0 is set to the name of that file.  If
>   Bash is started with the -c option (see Invoking
>   Bash), then $0 is set to the first argument after
>   the string to be executed, if one is present.
>   Otherwise, it is set to the filename used to invoke
>   Bash, as given by argument zero.
> 
> Whenever bash is executed with a script file, it sets $0 to the
> name of that file.  It only uses caller-provided values for $0 when
> a script file is not provided.
> 
>   $ (exec -a foo bash <<<'echo "$0"')
>   foo
>   $ (exec -a foo bash -s bar baz quux <<<'echo "$0"')
>   foo
>   $ (exec -a foo bash -c 'echo "$0"')
>   foo
>   $ (exec -a foo bash -c 'echo "$0"' bar baz quux)
>   bar
> 
> This behavior is standardized in POSIX [*] and is not unique to
> bash (I omitted ksh93, which actually does produce "foo" here).
> 
>   $ (exec -a foo zsh <(echo 'echo "$0"'))
>   /dev/fd/63
>   $ (exec -a foo dash <(echo 'echo "$0"'))
>   /dev/fd/63
>   $ (exec -a foo yash <(echo 'echo "$0"'))
>   /dev/fd/63
>   $ (exec -a foo mksh <(echo 'echo "$0"'))
>   /dev/fd/63
> 
> [*]: 
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html#tag_20_117_05
> 
> -- 
> vq


-- 

  Sergei



Re: More convenient tracing

2023-01-26 Thread Dale R. Worley
Greg Wooledge  writes:
> On Wed, Jan 25, 2023 at 03:00:27PM -0500, Dale R. Worley wrote:
>> 
>> Tracing with -x prints a lot of (usually) useless lines.
>> 
>> $ bash -x ./tt
>> [300+ lines of Bash initializations]
>> + echo 'Now in tt.'
>> Now in tt.
>
> Why does it do this?  Have you got BASH_ENV set to something in your
> environment?

I do have BASH_ENV set, to ~/.bashrc.  I need that so that my scripts
can use my .bashrc customizations.  Though I do know that I haven't
gotten the Bash startup scripts set correctly for the effects I want;
fixing that would cut most but by no means all of the "Bash
initializations" listed above.

Dale



Re: More convenient tracing

2023-01-26 Thread Greg Wooledge
On Thu, Jan 26, 2023 at 12:03:08PM -0500, Dale R. Worley wrote:
> I do have BASH_ENV set, to ~/.bashrc.  I need that so that my scripts
> can use my .bashrc customizations.

I strongly advise against this.  All of the things a script does should
be discoverable by reading the script, and any files that are explicitly
dotted in (sourced) by that script.

There shouldn't be any surprises coming in from the execution environment.

If your script needs external variables, it should explicitly dot in a
file that sets just those variables.  (Usually, /etc/default/ or ~/.config/
contains files of this type.)  Such a file should NOT be a user's .bashrc
because that can change on a whim, and may do things that the script
would neither expect nor desire.



Re: 'exec -a' and $0 substitution

2023-01-26 Thread Martin D Kealey
On Thu, 26 Jan 2023, 09:37 Sergei Trofimovich,  wrote:

> To the bug: looks like 'exec -a' does not work for bash scripts, but does
> work for other executables.
>

Be aware that the kernel is responsible for interpreting #! lines, not bash.

The kernel does several steps when it encounters an executable that starts
with the bytes '#' and '!'.
1. replacing argv[0] with the exec path, and
2. read bytes up to the first newline, skipping leading and trailing
whitespace;
3. if interstitial whitespace is present, split into two words at the first
run of whitespace
4. push these latter strings onto the front of argv
5. replace the exec path with a copy of (the new) argb[0]
6. re-start the execve procedure

Failing to make the substitution in step 1 would leave the interpreter
running but with no idea how to open the script so that it could run it.

-Martin

>