`history -r` can not read from /dev/stdin ?

2012-08-16 Thread Techlive Zheng
I was trying to reload the bash history file which changed by another
bash session with the following commands, but it wouldn't work, please
help me, why?

```
new_history=$(history -a /dev/stdout)
history -c
history -r
echo "$new_history" | history -r /dev/stdin
```



Re: `history -r` can not read from /dev/stdin ?

2012-08-16 Thread Techlive Zheng
2012/8/17 Chet Ramey :
> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote:
>> I was trying to reload the bash history file which changed by another
>> bash session with the following commands, but it wouldn't work, please
>> help me, why?
>>
>> ```
>> new_history=$(history -a /dev/stdout)
>> history -c
>> history -r
>> echo "$new_history" | history -r /dev/stdin
>> ```
>
> One possible cause that springs to mind is the fact that the `history -r'
> at the end of the pipeline is run in a subshell and cannot affect its
> parent's history list.
>
>
>
> --
> ``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/

So, How could I accomplish this kind of thing?



Re: `history -r` can not read from /dev/stdin ?

2012-08-16 Thread Techlive Zheng
2012/8/17 Chet Ramey :
> On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote:
>> 2012/8/17 Chet Ramey :
>>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote:
>>>> I was trying to reload the bash history file which changed by another
>>>> bash session with the following commands, but it wouldn't work, please
>>>> help me, why?
>>>>
>>>> ```
>>>> new_history=$(history -a /dev/stdout)
>>>> history -c
>>>> history -r
>>>> echo "$new_history" | history -r /dev/stdin
>>>> ```
>>>
>>> One possible cause that springs to mind is the fact that the `history -r'
>>> at the end of the pipeline is run in a subshell and cannot affect its
>>> parent's history list.
>>
>> So, How could I accomplish this kind of thing?
>
> Why not just use a regular file?
>
> --
> ``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/

Actually, I was tring to erase duplicate entries and share history
across bash sessions.'erasedups' in `HISTCONTROL` only have effect for
history list in the memory, so my solution is to load entire history
file into memory and save it after every command finished.

Here is what I am currently have in .bashrc, and it works as expected.

reload_history() {
local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
history -w
# This is necessay because we need
# to clear the last append signture
history -c
history -r
else
HISTTEMP=`mktemp`
history -a $HISTTEMP
history -c
history -r
history -r $HISTTEMP
history -w
rm $HISTTEMP
fi
HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
}

export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"

Considering `mkemp` then remove the temp file on every prompt command
is a little bit expensive, I want to directly pipe the output of the
`history -a` to `hisotory -r` like below, unfortunately, this wouldn't
work, because `history -r` could not handle /dev/stdin.

reload_history() {
local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
history -w
# This is necessay because we need
# to clear the last append signture
history -c
history -r
else
new_history=$(history -a /dev/stdout)
history -c
history -r
echo "$new_history" | history -r /dev/stdin
history -w
fi
HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
}

export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"



Re: `history -r` can not read from /dev/stdin ?

2012-08-17 Thread Techlive Zheng
2012/8/17 郑文辉(Techlive Zheng) :
> 2012/8/17 Chet Ramey :
>> On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote:
>>> 2012/8/17 Chet Ramey :
>>>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote:
>>>>> I was trying to reload the bash history file which changed by another
>>>>> bash session with the following commands, but it wouldn't work, please
>>>>> help me, why?
>>>>>
>>>>> ```
>>>>> new_history=$(history -a /dev/stdout)
>>>>> history -c
>>>>> history -r
>>>>> echo "$new_history" | history -r /dev/stdin
>>>>> ```
>>>>
>>>> One possible cause that springs to mind is the fact that the `history -r'
>>>> at the end of the pipeline is run in a subshell and cannot affect its
>>>> parent's history list.
>>>
>>> So, How could I accomplish this kind of thing?
>>
>> Why not just use a regular file?
>>
>> --
>> ``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/
>
> Actually, I was tring to erase duplicate entries and share history
> across bash sessions.'erasedups' in `HISTCONTROL` only have effect for
> history list in the memory, so my solution is to load entire history
> file into memory and save it after every command finished.
>
> Here is what I am currently have in .bashrc, and it works as expected.
>
> reload_history() {
> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
> history -w
> # This is necessay because we need
> # to clear the last append signture
> history -c
> history -r
> else
> HISTTEMP=`mktemp`
> history -a $HISTTEMP
> history -c
> history -r
> history -r $HISTTEMP
> history -w
> rm $HISTTEMP
> fi
> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
> }
>
> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"
>
> Considering `mkemp` then remove the temp file on every prompt command
> is a little bit expensive, I want to directly pipe the output of the
> `history -a` to `hisotory -r` like below, unfortunately, this wouldn't
> work, because `history -r` could not handle /dev/stdin.
>
> reload_history() {
> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
> history -w
> # This is necessay because we need
> # to clear the last append signture
> history -c
> history -r
> else
> new_history=$(history -a /dev/stdout)
> history -c
> history -r
> echo "$new_history" | history -r /dev/stdin
> history -w
> fi
> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
> }
>
> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"

I have just checked out the source of bash and found that `read()` or
`mmap` is used to read the history file as below. The following code
could not handle /dev/stdin properly. As I am not a C expert, I could
not come up a patch for this, maybe someone here could give me a
little help?

>From lib/readline/histfile.c:200

#ifdef HISTORY_USE_MMAP
  /* We map read/write and private so we can change newlines to NULs without
 affecting the underlying object. */
  buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE,
MAP_RFLAGS, file, 0);
  if ((void *)buffer == MAP_FAILED)
{
  errno = overflow_errno;
  goto error_and_exit;
}
  chars_read = file_size;
#else
  buffer = (char *)malloc (file_size + 1);
  if (buffer == 0)
{
  errno = overflow_errno;
  goto error_and_exit;
}

  chars_read = read (file, buffer, file_size);
#endif



Re: `history -r` can not read from /dev/stdin ?

2012-08-17 Thread Techlive Zheng
2012/8/17 郑文辉(Techlive Zheng) :
> 2012/8/17 郑文辉(Techlive Zheng) :
>> 2012/8/17 Chet Ramey :
>>> On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote:
>>>> 2012/8/17 Chet Ramey :
>>>>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote:
>>>>>> I was trying to reload the bash history file which changed by another
>>>>>> bash session with the following commands, but it wouldn't work, please
>>>>>> help me, why?
>>>>>>
>>>>>> ```
>>>>>> new_history=$(history -a /dev/stdout)
>>>>>> history -c
>>>>>> history -r
>>>>>> echo "$new_history" | history -r /dev/stdin
>>>>>> ```
>>>>>
>>>>> One possible cause that springs to mind is the fact that the `history -r'
>>>>> at the end of the pipeline is run in a subshell and cannot affect its
>>>>> parent's history list.
>>>>
>>>> So, How could I accomplish this kind of thing?
>>>
>>> Why not just use a regular file?
>>>
>>> --
>>> ``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/
>>
>> Actually, I was tring to erase duplicate entries and share history
>> across bash sessions.'erasedups' in `HISTCONTROL` only have effect for
>> history list in the memory, so my solution is to load entire history
>> file into memory and save it after every command finished.
>>
>> Here is what I am currently have in .bashrc, and it works as expected.
>>
>> reload_history() {
>> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
>> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
>> history -w
>> # This is necessay because we need
>> # to clear the last append signture
>> history -c
>> history -r
>> else
>> HISTTEMP=`mktemp`
>> history -a $HISTTEMP
>> history -c
>> history -r
>> history -r $HISTTEMP
>> history -w
>> rm $HISTTEMP
>> fi
>> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
>> }
>>
>> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"
>>
>> Considering `mkemp` then remove the temp file on every prompt command
>> is a little bit expensive, I want to directly pipe the output of the
>> `history -a` to `hisotory -r` like below, unfortunately, this wouldn't
>> work, because `history -r` could not handle /dev/stdin.
>>
>> reload_history() {
>> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1`
>> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then
>> history -w
>> # This is necessay because we need
>> # to clear the last append signture
>> history -c
>> history -r
>> else
>> new_history=$(history -a /dev/stdout)
>> history -c
>> history -r
>> echo "$new_history" | history -r /dev/stdin
>> history -w
>> fi
>> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1`
>> }
>>
>> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"
>
> I have just checked out the source of bash and found that `read()` or
> `mmap` is used to read the history file as below. The following code
> could not handle /dev/stdin properly. As I am not a C expert, I could
> not come up a patch for this, maybe someone here could give me a
> little help?
>
> From lib/readline/histfile.c:200
>
> #ifdef HISTORY_USE_MMAP
>   /* We map read/write and private so we can change newlines to NULs without
>  affecting the underlying object. */
>   buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE,
> MAP_RFLAGS, file, 0);
>   if ((void *)buffer == MAP_FAILED)
> {
>   errno = overflow_errno;
>   goto error_and_exit;
> }
>   chars_read = file_size;
> #else
>   buffer = (char *)malloc (file_size + 1);
>   if (buffer == 0)
> {
>   errno = overflow_errno;
>   goto error_and_exit;
> }
>
>   chars_read = read (file, buffer, file_size);
> #endif

I have tried using a named pipe or process substition, neither worked.



`bash --debugger` in interactive mode

2012-08-17 Thread Techlive Zheng
I happened to have `shopt -s extdebug` in my .bashrc recently.

After a new bash session started, I got the following output.

bash debugger, bashdb, release 4.2-0.8

Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
Rocky Bernstein
This is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under certain
conditions.

** Internal debug error _Dbg_is_file(): file argument null
bash: _Dbg_filenames[$fullname]: bad array subscript

I guess `--debugger` or `shopt -s extdebug` is not supposed to be run
under interactive mode?

If so, maybe a detection should be done for this situation?



Re: `bash --debugger` in interactive mode

2012-08-19 Thread Techlive Zheng
2012/8/20 Chet Ramey :
> On 8/18/12 1:55 AM, 郑文辉(Techlive Zheng) wrote:
>> I happened to have `shopt -s extdebug` in my .bashrc recently.
>>
>> After a new bash session started, I got the following output.
>>
>> bash debugger, bashdb, release 4.2-0.8
>>
>> Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
>> Rocky Bernstein
>> This is free software, covered by the GNU General Public License,
>> and you are
>> welcome to change it and/or distribute copies of it under certain
>> conditions.
>>
>> ** Internal debug error _Dbg_is_file(): file argument null
>> bash: _Dbg_filenames[$fullname]: bad array subscript
>>
>> I guess `--debugger` or `shopt -s extdebug` is not supposed to be run
>> under interactive mode?
>>
>> If so, maybe a detection should be done for this situation?
>
> Thanks for the report.  I will put something in for the next bash release.
>
> 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/

I just want poin it out that there are some bash tricks which require
using `set -o functrace` and `shopt -s extdebug` in interactive mode
to make the DEBUG trap to be invoked in ( ) subshells, see
<https://github.com/revans/bash-it/blob/master/lib/preexec.bash#L115>,
maybe this is something that should be done in `bashdb`?



Re: Indirect expansion and arrays

2012-10-02 Thread Techlive Zheng


> On 7/29/10 4:55 PM, Bernd Eggink wrote:
> > It seems that indirect expansion doesn't work with arrays:
> > 
> > $ a=(x y z)
> > $ b=a
> > $ echo "${!b[0]} ${!b[1]} ${!b[2]}"
> > x
> > 
> > Is that intended? The documentation isn't explicit about it.

> It does, but it doesn't work in the way you are trying.  The `!' binds to
> an entire variable reference, in this case 'b[0]'.  The idea behind that
> was to permit the use of an array of variable names, for instance, that
> could be easily referenced using indirect expansion.

> The following code will display
> "x variable y variable z variable"

> a=(x y z)

> x='x variable'
> y='y variable'
> z='z variable'

> echo "${!a[0]} ${!a[1]} ${!a[2]}"

> 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/

I think that indirect reference for fash variable should be used literally.

$ a=(x y z)
$ b=a[@]
$ echo "${!b}" # this would work

Combine with Chet Ramey's reply, a strucure like below would work.

$ c=(a[0] a[1] a[2])
$ echo "${!c[0]} ${!c[1]} ${!c[2]}" #this would work too


-- 
View this message in context: 
http://old.nabble.com/Indirect-expansion-and-arrays-tp29300541p34504291.html
Sent from the Gnu - Bash mailing list archive at Nabble.com.