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 chet.ra...@gmail.com wrote:

 On 2/12/13 11:40 AM, Pierre Gaston wrote:
  On Tue, Feb 12, 2013 at 6:07 PM, Matei David matei.da...@gmail.com
 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 chet.ra...@case.edu 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 matei.da...@gmail.com wrote:

 Thank you for the explanation.


 On Tue, Feb 12, 2013 at 8:32 PM, Chet Ramey chet.ra...@gmail.com wrote:

 On 2/12/13 11:40 AM, Pierre Gaston wrote:
  On Tue, Feb 12, 2013 at 6:07 PM, Matei David matei.da...@gmail.com
 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/