4.3 compgen behavior change (quoted arg)

2013-02-13 Thread Raphaël Droz
I'm not sure whether or not this is to be expected.

$ echo $BASH_VERSION 
4.2.42(1)-release
$ touch a.log
$ compgen -f -X '!*.log' -- \'\'
$


$ echo $BASH_VERSION 
4.3.0(3)-devel
$ touch a.log
$ compgen -f -X '!*.log' -- \'\'
a.log
$


This kind of "quoted" call is used by bash-completion _filedir
I didn't see a change notice in NEWS-4.3 about it.
I don't know which behavior is the "correct" one.


regards




Re: 4.3 compgen behavior change (quoted arg)

2013-02-13 Thread Chet Ramey
On 2/13/13 5:46 AM, Raphaël Droz wrote:
> I'm not sure whether or not this is to be expected.
> 
> $ echo $BASH_VERSION 
> 4.2.42(1)-release
> $ touch a.log
> $ compgen -f -X '!*.log' -- \'\'
> $
> 
> 
> $ echo $BASH_VERSION 
> 4.3.0(3)-devel
> $ touch a.log
> $ compgen -f -X '!*.log' -- \'\'
> a.log
> $
> 
> 
> This kind of "quoted" call is used by bash-completion _filedir
> I didn't see a change notice in NEWS-4.3 about it.
> I don't know which behavior is the "correct" one.

Here's the comment associated with the change:

  /* remove backslashes quoting special characters in filenames. */
  /* There are roughtly three paths we can follow to get here:
1.  complete -f
2.  compgen -f "$word" from a completion function
3.  compgen -f "$word" from the command line
 They all need to be handled.

 In the first two cases, readline will run the filename dequoting
 function in rl_filename_completion_function if it found a filename
 quoting character in the word to be completed
 (rl_completion_found_quote).  We run the dequoting function here
 if we're running compgen, we're not completing, and the
 rl_filename_completion_function won't dequote the filename
 (rl_completion_found_quote == 0). */

The idea is to make compgen, when run from the command line, more closely
emulate what it will do when run by readline via word completion.  There
are obviously heuristics involved.

Chet



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



Re: Is this intended behavior??

2013-02-13 Thread Chet Ramey
On 2/11/13 2:25 PM, Bruce Korb wrote:
>> /tmp
>> $ echo "$PS1"
>> \w\n\$ 
>> /tmp
>> $ mkdir -p ZZ/a/b/c
>> /tmp
>> $ pushd ZZ
>> /tmp/ZZ /tmp
>> /tmp/ZZ
>> $ pushd a
>> /tmp/ZZ/a /tmp/ZZ /tmp
>> /tmp/ZZ/a
>> $ pushd b/c
>> /tmp/ZZ/a/b/c /tmp/ZZ/a /tmp/ZZ /tmp
>> /tmp/ZZ/a/b/c
>> $ popd /var/tmp
>> /tmp/ZZ/a/b/c /tmp/ZZ/a /tmp/ZZ
>> /tmp/ZZ/a/b/c
>> $ popd /var/tmp
>> /tmp/ZZ/a/b/c /tmp/ZZ/a
>> /tmp/ZZ/a/b/c
>> $ 
> 
> It is behaving as if it were seeing the "-0" option.

It's unspecified behavior.  popd doesn't take any `non-option' arguments.
As soon as you specify one, you can't really expect to know what will
happen without experimentation or reading the source.

/var/tmp gets translated to the equivalent of -0 (if you're curious, it's
because `/' isn't `+' and the default directory index is 0).

It should probably be an error instead.

Chet

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



Re: eval doesn't close file descriptor?

2013-02-13 Thread Matei David
Thank you for the explanation.


On Tue, Feb 12, 2013 at 8:32 PM, Chet Ramey  wrote:

> On 2/12/13 11:40 AM, Pierre Gaston wrote:
> > On Tue, Feb 12, 2013 at 6:07 PM, Matei David 
> wrote:
> >
> >> Ok, but I see the same behaviour when eval runs in a subshell:
> >>
> >> $ bash -c 'llfd () { echo "pid:$BASHPID" >&2; ls -l /proc/$BASHPID/fd/
> >>> &2; }; x=3; eval "exec $x>/dev/null"; llfd; echo | eval "llfd $x>&-"'
> >> [same output, fd 10 open, pointing to /dev/null, even though it's a
> >> subshell]
> >>
> >
> > eval runs in a subshell, but it's the same thing inside this subshell.
> > eg you could have: echo | { eval "llfd "$x>&-"; echo blah >&3; }
> >
> > Bash could optimize this once it realizes there's only one command, but
> > it's probably not that simple to implement.
>
> The basic flow is like this for any builtin command or shell function that
> has a redirection (let's choose 'llfd 3>&-').
>
> 1.  The redirection is performed in the current shell, noting that it
> should be `undoable'.  That takes three steps:
>
> 1a. In this case, since fd 3 is in use, we dup it (to fd 10) and mark fd
> 10 as close-on-exec.  We add a separate redirection to an internal
> list  that basically says "close fd 10".  Then we add another
> redirection to the front of the same internal list that says "dup fd
> 10 back to fd 3".  Let's call this list "redirection_undo_list".  We
> will use it to restore the original state after the builtin or
> function completes.
>
> 1b. Take the first redirection from step 1a and add it to a separate
> internal list that will clean up internal redirections in the case
> that exec causes the redirections to be preserved, and not undone.
> Let's call this list "exec_redirection_undo_list".
>
> 1c. Perform the redirection.  Here, that means close fd 3.
>
> [perform step 1 for each redirection associated with the command]
>
> 2.  If we're running the exec builtin, throw away the list from 1a.  If
> we're not running the exec builtin, throw away the list from 1b.  Save
> a handle to the list we didn't discard.
>
> 3.  Run the function or builtin.
>
> 4.  Take the list saved in step 2 and perform the redirections to
> restore the previous state.  Here, that means we dup fd 10 back to fd
> 3, then close fd 10.
>
> If you look at the steps, it should be clear why fd 10 is still open when
> llfd executes.
>
> Bash `cheats' when running builtins or shell functions in pipelines or
> other subshells.  It knows it's already going to be in a child process
> when it performs the redirections, so it doesn't bother setting up the
> structures to undo them.
>
> Chet
>
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>  ``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, ITS, CWRUc...@case.edu
> http://cnswww.cns.cwru.edu/~chet/
>


Re: Is this intended behavior??

2013-02-13 Thread Bruce Korb
Hi,

On Wed, Feb 13, 2013 at 9:01 AM, Chet Ramey  wrote:
> On 2/11/13 2:25 PM, Bruce Korb wrote:
[...]
>>> /tmp/ZZ/a/b/c /tmp/ZZ/a /tmp/ZZ
>>> /tmp/ZZ/a/b/c
>>> $ popd /var/tmp
>>> /tmp/ZZ/a/b/c /tmp/ZZ/a
>>> /tmp/ZZ/a/b/c
>>> $
>>
>> It is behaving as if it were seeing the "-0" option.
>
> It's unspecified behavior.  popd doesn't take any `non-option' arguments.
> As soon as you specify one, you can't really expect to know what will
> happen without experimentation or reading the source.

Not my source.  I was trying to replace crufty code. :)

> /var/tmp gets translated to the equivalent of -0 (if you're curious, it's
> because `/' isn't `+' and the default directory index is 0).
>
> It should probably be an error instead.

Perfect!  I was editing someone else's code and replacing pushd/popd with
cd $dir/cd $OLDPWD when I discovered this bizarre behavior because someone
had coded up "popd $WORKDIR" with that work directory being a full path.
I replaced that with "cd $OLDPWD" and the script failed.

Either an error or ignore the thing, just not something unanticipatable. :)

Thank you! - Bruce



Re: eval doesn't close file descriptor?

2013-02-13 Thread Matei David
Another thing I tried was to open a fd with <() and use it later in a shell
function. Surprisingly, the fd disappears (is closed) if the shell executes
something unrelated in subshell:

$ bash -c 'xxx () { echo "got arg: $1" >&2; ls -gG /proc/$BASHPID/fd >&2;
(echo "subprocess" >&2); ls -gG /proc/$BASHPID/fd >&2; cat $1; }; . lfd.sh;
xxx <(echo "hi")'
got arg: /dev/fd/63
total 0
lrwx-- 1 64 Feb 13 12:28 0 -> /dev/pts/9
lrwx-- 1 64 Feb 13 12:28 1 -> /dev/pts/9
lrwx-- 1 64 Feb 13 12:28 2 -> /dev/pts/9
lr-x-- 1 64 Feb 13 12:28 63 -> pipe:[5474849]
lr-x-- 1 64 Feb 13 12:28 8 -> /proc/4520/auxv
subprocess
total 0
lrwx-- 1 64 Feb 13 12:28 0 -> /dev/pts/9
lrwx-- 1 64 Feb 13 12:28 1 -> /dev/pts/9
lrwx-- 1 64 Feb 13 12:28 2 -> /dev/pts/9
lr-x-- 1 64 Feb 13 12:28 8 -> /proc/4520/auxv
cat: /dev/fd/63: No such file or directory
$

Note how 63 is open before '(echo)' and closed after. Is this expected?


On Wed, Feb 13, 2013 at 12:06 PM, Matei David  wrote:

> Thank you for the explanation.
>
>
> On Tue, Feb 12, 2013 at 8:32 PM, Chet Ramey  wrote:
>
>> On 2/12/13 11:40 AM, Pierre Gaston wrote:
>> > On Tue, Feb 12, 2013 at 6:07 PM, Matei David 
>> wrote:
>> >
>> >> Ok, but I see the same behaviour when eval runs in a subshell:
>> >>
>> >> $ bash -c 'llfd () { echo "pid:$BASHPID" >&2; ls -l /proc/$BASHPID/fd/
>> >>> &2; }; x=3; eval "exec $x>/dev/null"; llfd; echo | eval "llfd $x>&-"'
>> >> [same output, fd 10 open, pointing to /dev/null, even though it's a
>> >> subshell]
>> >>
>> >
>> > eval runs in a subshell, but it's the same thing inside this subshell.
>> > eg you could have: echo | { eval "llfd "$x>&-"; echo blah >&3; }
>> >
>> > Bash could optimize this once it realizes there's only one command, but
>> > it's probably not that simple to implement.
>>
>> The basic flow is like this for any builtin command or shell function that
>> has a redirection (let's choose 'llfd 3>&-').
>>
>> 1.  The redirection is performed in the current shell, noting that it
>> should be `undoable'.  That takes three steps:
>>
>> 1a. In this case, since fd 3 is in use, we dup it (to fd 10) and mark fd
>> 10 as close-on-exec.  We add a separate redirection to an internal
>> list  that basically says "close fd 10".  Then we add another
>> redirection to the front of the same internal list that says "dup fd
>> 10 back to fd 3".  Let's call this list "redirection_undo_list".  We
>> will use it to restore the original state after the builtin or
>> function completes.
>>
>> 1b. Take the first redirection from step 1a and add it to a separate
>> internal list that will clean up internal redirections in the case
>> that exec causes the redirections to be preserved, and not undone.
>> Let's call this list "exec_redirection_undo_list".
>>
>> 1c. Perform the redirection.  Here, that means close fd 3.
>>
>> [perform step 1 for each redirection associated with the command]
>>
>> 2.  If we're running the exec builtin, throw away the list from 1a.  If
>> we're not running the exec builtin, throw away the list from 1b.  Save
>> a handle to the list we didn't discard.
>>
>> 3.  Run the function or builtin.
>>
>> 4.  Take the list saved in step 2 and perform the redirections to
>> restore the previous state.  Here, that means we dup fd 10 back to fd
>> 3, then close fd 10.
>>
>> If you look at the steps, it should be clear why fd 10 is still open when
>> llfd executes.
>>
>> Bash `cheats' when running builtins or shell functions in pipelines or
>> other subshells.  It knows it's already going to be in a child process
>> when it performs the redirections, so it doesn't bother setting up the
>> structures to undo them.
>>
>> Chet
>>
>> --
>> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>>  ``Ars longa, vita brevis'' - Hippocrates
>> Chet Ramey, ITS, CWRUc...@case.edu
>> http://cnswww.cns.cwru.edu/~chet/
>>
>
>