Next word of alias to alias that end with is not checked for alias

2023-01-12 Thread anonymous4feedb...@outlook.com
Dear dir or madam,

For the following script:
alias a1='echo '
alias a2=a1
alias foo=bar
a2 foo
bash outputs ‘foo’, instead of ‘bar’.

GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu) on archlinux as 
windows subsystem for linux

Thanks.



Re: errexit is not suspended in a pipeline

2023-01-12 Thread Chet Ramey

On 1/11/23 11:22 PM, Quinn Grier wrote:


I see. I had mistakenly thought that Bash's set -e description was
definitively listing the contexts in which set -e is ignored, not just
contexts in which set -e may not have the intended effect.


It lists the scenarios where the shell will not exit.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/




Re: Next word of alias to alias that end with is not checked for alias

2023-01-12 Thread Chet Ramey

On 1/11/23 10:43 PM, anonymous4feedb...@outlook.com wrote:

Dear dir or madam,

For the following script:
alias a1='echo '
alias a2=a1
alias foo=bar
a2 foo
bash outputs ‘foo’, instead of ‘bar’.


Bash has never extended the `expand next word' semantics to multiple-level
alias expansion like this, and no one has missed it.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/




Re: Next word of alias to alias that end with is not checked for alias

2023-01-12 Thread Greg Wooledge
On Thu, Jan 12, 2023 at 03:43:15AM +, anonymous4feedb...@outlook.com wrote:
> Dear dir or madam,
> 
> For the following script:
> alias a1='echo '
> alias a2=a1
> alias foo=bar
> a2 foo
> bash outputs ‘foo’, instead of ‘bar’.
> 
> GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu) on archlinux as 
> windows subsystem for linux

First thing first: aliases are not used in scripts, unless bash is
invoked in POSIX mode, or the "expand_aliases" shopt is enabled.
So either this wasn't really a script (i.e. you ran these commands at
an interactive shell), or else this wasn't the *entire* script.

Second thing: the command in question here is "a2 foo", where a2 is
an alias.  But the a2 alias doesn't end with a space.  So there's no
reason to expect that the special "alias ends with a space" processing
would occur here.

If you used "a1 foo" then it *would* occur.

You're expecting an alias that aliases an alias to inherit the special
hacks of the alias that it's aliasing.  It doesn't.

If you want a2 to have the space-hack behavior, put a space after it.

Here's a working version:


unicorn:~$ cat foo
#!/bin/bash
shopt -s expand_aliases

alias a1='echo '
alias a2='a1 '
alias foo=bar

a1 foo one
a2 foo two
unicorn:~$ ./foo
bar one
bar two


In my opinion, the only bug here is in your script, not in bash.

Also my opinion: aliases are disabled in bash scripts for a reason.
They're ugly and horrible, and they don't promote good programming
practices.  Whatever you're trying to do here, I doubt aliases are
the best way to do it.  Consider using functions instead.



Re: Next word of alias to alias that end with is not checked for alias

2023-01-12 Thread Robert Elz
Date:Thu, 12 Jan 2023 10:56:33 -0500
From:Chet Ramey 
Message-ID:  <0f03dd45-3e1a-54b1-f884-d3fb2c1c7...@case.edu>

  | Bash has never extended the `expand next word' semantics to multiple-level
  | alias expansion like this, and no one has missed it.

Bash is unique amongst shells in this - all other shells, including all
ksh variants (though I don't have ksh88 to test) do produce "bar" from
that test case.

Unless there's some particular reason to keep it like this, this is something
that perhaps should change (and really should for posix conformance in posix
mode).   There's nothing in posix about the "space at the end" being only
applicable to the first alias located - every alias expansion should apply 
that.

Of course, all mention of aliases should really be removed from
POSIX - aliases are even worse than "set -e".

kre




Re: Next word of alias to alias that end with is not checked for alias

2023-01-12 Thread Greg Wooledge
On Fri, Jan 13, 2023 at 01:59:55AM +0700, Robert Elz wrote:
> Date:Thu, 12 Jan 2023 10:56:33 -0500
> From:Chet Ramey 
> Message-ID:  <0f03dd45-3e1a-54b1-f884-d3fb2c1c7...@case.edu>
> 
>   | Bash has never extended the `expand next word' semantics to multiple-level
>   | alias expansion like this, and no one has missed it.
> 
> Bash is unique amongst shells in this - all other shells, including all
> ksh variants (though I don't have ksh88 to test) do produce "bar" from
> that test case.

The ksh88 installed as /usr/bin/ksh on HP-UX 10.20 prints "bar".



SIGINT handling during async functions

2023-01-12 Thread Tycho Kirchner

Hi,
we found quite some inconsistency and weirdness in the handling of SIGINT's 
during async function calls and were wondering, whether those are expected. All 
calls were executed from a script with jobcontrol turned off (set +m) while 
pressing Ctrl+C shortly afterwards. In summary:
The main INT handler is never executed in foofunc (is that expected?) while the new (default) handler 
either aborts command execution in case of 'foofunc &' or continues execution in case of '{ foofunc; 
} &'. While on 'foofunc &' 'trap -p' at the beginning of foofunc (wrongly) prints the main 
handler, in case of '{ foofunc; } &' it suddenly prints the ignore handler "trap -- '' 
SIGINT" and remains indeed uninterruptible. Thus printing the trap apparently changes bash's 
behavior.

Tested bash versions:
GNU bash, Version 5.1.4(1)-release (x86_64-pc-linux-gnu)
GNU bash, Version 5.2.2(1)-release (x86_64-pc-linux-gnu)
on Debian Bullseye.

Thanks and kind regards
Tycho


t='echo INT ${FUNCNAME[0]-main} >&2'
trap "$t" INT
foofunc(){ sleep 3; echo foo >&2; }
foofunc &
sleep 5
--> INT main
# foofunc INT-handler is reset to default ('foo' is not printed).
# Note that 'trap -p' within foofunc wrongly prints above INT handler.



t='echo INT ${FUNCNAME[0]-main} >&2'
trap "$t" INT
foofunc(){ trap "$t" INT; sleep 3; echo foo >&2; }
foofunc &
sleep 5
--> INT main
INT foofunc
foo
# foofunc custom INT-handler works.


t='echo INT ${FUNCNAME[0]-main} >&2'
trap "$t" INT
foofunc(){ sleep 3; echo foo >&2; }
{ foofunc; } &
sleep 5
--> INT main
foo
# Opposing to 'foofunc &' foo _is_ printed so apparently we have a
# different default trap handler here.


t='echo INT ${FUNCNAME[0]-main} >&2'
trap "$t" INT
foofunc(){ trap -p; sleep 3; echo foo >&2; }
{ foofunc; } &
sleep 5
--> trap -- '' SIGINT
^CINT main
$ foo
# Here, when the trap is printed, INT is reported as "ignored" and foofunc
# becomes indeed uninterruptible. So, 'trap -p' changes bash's behavior.




Re: SIGINT handling during async functions

2023-01-12 Thread Robert Elz
Date:Fri, 13 Jan 2023 00:34:02 +0100
From:Tycho Kirchner 
Message-ID:  <7d59c17d-792e-0ac7-fd86-b3b2e7d4b...@mail.de>

  | we found quite some inconsistency and weirdness
  | in the handling of SIGINT's during async function calls

Not inconsistent or weird, and has nothing to do with
function calls.

  | and were wondering, whether those are expected.

Expected and required.

  | The main INT handler is never executed in foofunc [...]
  | Thus printing the trap apparently changes bash's behavior.

Nonsense (the conclusion).

When an async command (any command, not just functions,
or blocks enclosed in { } ) is run with job control
disabled, SIGINT is ignored for that async command.
(SIGQUIT too).

That has been the way shells work since before either
the Bourne shell (and all later shells based upon it,
like bash) or job control, were invented.

That is all you are seeing here.

kre



Re: SIGINT handling during async functions

2023-01-12 Thread Robert Elz
Oh, the differences in what trap -p is printing is because
of special case handling for trap in a subshell environment,
when the trap command is the first (maybe only) command
executed (details vary between shells).  That is mostly
intended to allow T=$(trap -p) to work, but is usually applied
to any subsell environment (it is simpler that way).
An async command is a subshell environment.

When you do foofunc& the trap command thus prints the
trap from the parent's environment, but when you  embed
that ina group, the traps get reset to those for the
subshell before the trap command gets to run, so you see
that instead.

Everything is working as intended.

kre




Re: SIGINT handling during async functions

2023-01-12 Thread Tycho Kirchner




Am 13.01.23 um 03:02 schrieb Robert Elz:

 Date:Fri, 13 Jan 2023 00:34:02 +0100
 From:Tycho Kirchner 
 Message-ID:  <7d59c17d-792e-0ac7-fd86-b3b2e7d4b...@mail.de>

   | we found quite some inconsistency and weirdness
   | in the handling of SIGINT's during async function calls

Not inconsistent or weird, and has nothing to do with
function calls.

   | and were wondering, whether those are expected.

Expected and required.

   | The main INT handler is never executed in foofunc [...]
   | Thus printing the trap apparently changes bash's behavior.

Nonsense (the conclusion)> 
When an async command (any command, not just functions,

or blocks enclosed in { } ) is run with job control
disabled, SIGINT is ignored for that async command.
(SIGQUIT too).

That has been the way shells work since before either
the Bourne shell (and all later shells based upon it,
like bash) or job control, were invented.

That is all you are seeing here.

kre


Dear Robert Elz,
thanks for the quick response. However, did you actually actually put the short 
snippets into a script, executed it and verified that their behavior is the 
same? In particular, did you check, whether the respective 'sleep' commands 
kept running, after hitting Ctrl+C? On my test system, the 'sleep 3' within 
foofounc **is** killed in the first three code snippets, proving your 
statements wrong. **Only** in case of the 4th snippet, where the trap is 
printed at the beginning of foofunc, the 'sleep 3' command keeps running after 
hitting Ctrl+C.
Let me give another example. Put the following commands into a script test.sh 
and execute it.
__
bash -c 'echo first; trap -p' & wait
{ bash -c 'echo second; trap -p'; } & wait
{ trap -p >/dev/null; bash -c 'echo third; trap -p'; } & wait
__

$ ./test.sh
first
trap -- '' SIGINT
trap -- '' SIGQUIT
second
third
trap -- '' SIGINT
__

So, even in this simple case, differences are observable.
Kind regards
Tycho