Feature request - make type show that a builtin is a loadable

2022-10-23 Thread Geir Hauge
I think it's a good idea for the type builtin to distinguish between
static and loadable builtins, and for debugging scripts that use
loadable builtins, it would be useful to be able to see which file got
loaded. For example in cases where BASH_LOADABLES_PATH was
unintentionally unset or set to a wrong path.

I had a go at implementing it and cobbled together the attached patch.
It extends struct builtin with a new path field that gets set to the
path that was passed to dlopen. The type builtin then includes that path
in its output if it is set.

$ ./bash -c 'enable csv; type [ csv'
[ is a shell builtin
csv is a shell builtin (/usr/local/lib/bash/csv)
$ BASH_LOADABLES_PATH=$PWD/examples/loadables ./bash -c 'enable csv; type [ 
csv'
[ is a shell builtin
csv is a shell builtin (/Users/geirha/bash/examples/loadables/csv)

Continuing on the debugging aspect, I think it would also be useful if
enable would warn or fail if you try to enable a loadable builtin that
was built against a different bash version. The easiest is probably to
embed the bash version inside the loadable file somehow, and compare
that when loading. Giving something like:

$ enable csv
bash: enable: /usr/local/lib/bash/csv: builtin was built for bash-5.1.16

Not sure how to go about implementing that though, or if it's even a
good approach. After all, you could potentially have multiple bash
builds of the same version with different configure options, which could
potentially leave out some function the loadable builtin expects to use.

-- 
Geir Hauge
diff --git a/builtins.h b/builtins.h
index 01565935..b4c71274 100644
--- a/builtins.h
+++ b/builtins.h
@@ -57,6 +57,7 @@ struct builtin {
   char * const *long_doc;  /* NULL terminated array of strings. */
   const char *short_doc;   /* Short version of documentation. */
   char *handle;/* for future use */
+  char *path;  /* path of loadable builtin. */
 };
 
 /* Found in builtins.c, created by builtins/mkbuiltins. */
diff --git a/builtins/enable.def b/builtins/enable.def
index 27d341a6..ae861b96 100644
--- a/builtins/enable.def
+++ b/builtins/enable.def
@@ -340,6 +340,7 @@ dyn_load_builtin (list, flags, filename)
 #endif
 
   handle = 0;
+  load_path = 0;
   if (absolute_program (filename) == 0)
 {
   loadables_path = get_string_value ("BASH_LOADABLES_PATH");
@@ -353,7 +354,6 @@ dyn_load_builtin (list, flags, filename)
 #else
  handle = dlopen (load_path, RTLD_LAZY);
 #endif /* !_AIX */
- free (load_path);
}
}
 }
@@ -377,6 +377,8 @@ dyn_load_builtin (list, flags, filename)
  if (name != filename)
free (name);
}
+  if (load_path)
+free (load_path);
   return (EX_NOTFOUND);
 }
 
@@ -434,6 +436,7 @@ dyn_load_builtin (list, flags, filename)
   if (flags & SPECIAL)
b->flags |= SPECIAL_BUILTIN;
   b->handle = handle;
+  b->path = load_path ? savestring(load_path) : NULL;
 
   if (old_builtin)
{
@@ -444,6 +447,9 @@ dyn_load_builtin (list, flags, filename)
  new_builtins[new++] = b;
 }
 
+  if (load_path)
+free (load_path);
+
   if (replaced == 0 && new == 0)
 {
   free (new_builtins);
diff --git a/builtins/type.def b/builtins/type.def
index a8e47c0a..fc7099db 100644
--- a/builtins/type.def
+++ b/builtins/type.def
@@ -52,6 +52,7 @@ $END
 
 #include 
 
+#include "../builtins.h"
 #include "../bashtypes.h"
 #include "posixstat.h"
 
@@ -289,6 +290,7 @@ describe_command (command, dflags)
 }
 
   /* Command is a builtin? */
+  struct builtin *b = builtin_address_internal(command, 0);
   if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
 {
   if (dflags & CDESC_TYPE)
@@ -297,6 +299,8 @@ describe_command (command, dflags)
{
  if (posixly_correct && find_special_builtin (command) != 0)
printf (_("%s is a special shell builtin\n"), command);
+ else if (b->path)
+   printf (_("%s is a shell builtin (%s)\n"), command, b->path);
  else
printf (_("%s is a shell builtin\n"), command);
}


cut loadable outputs extra newlines

2022-08-10 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin20.6.0
Compiler: gcc
Compilation CFLAGS: -g -O2
uname output: Darwin macspear 20.6.0 Darwin Kernel Version 20.6.0: Tue Apr 19 2$
Machine Type: x86_64-apple-darwin20.6.0

Bash Version: 5.2
Patch Level: 0
Release Status: rc3

Description:
examples/loadables/cut.c uses zgetline, which includes the newline
delimiter in the line it reads, but the rest of the code expects the
line to not contain the newline.

Repeat-By:
$ ./bash -c 'enable -f examples/loadables/cut cut ; cut -c4-' <<< 
$'abcdef\nghijkl'
def

jkl

$

Fix:
Strip off the newline right after reading the line.  Attached patch
fixes the problem.
diff --git a/examples/loadables/cut.c b/examples/loadables/cut.c
index ed4972d2..280c5231 100644
--- a/examples/loadables/cut.c
+++ b/examples/loadables/cut.c
@@ -417,6 +417,8 @@ cutfile (v, list, ops)
   while ((n = zgetline (fd, &line, &llen, '\n', unbuffered_read)) != -1)
{
  QUIT;
+ if (line[n] == '\n')
+   line[n] = '\0';
  cutline (v, line, ops);   /* can modify line */
}
   if (fd > 0)


Can't wait for process substitution redirected for a subshell

2018-04-24 Thread Geir Hauge
Waiting on a process substitution that is used in redirection for a
command grouping works, but not when using a subshell in place of that
command grouping:

$ TIMEFORMAT=%R
$ time bash -c '{ :; } 2> >(sleep 2); wait "$!"'
2.013
$ time bash -c '(:) 2> >(sleep 2); wait "$!"'
bash: line 0: wait: `': not a pid or valid job spec
0.008

I'd expect those two cases to behave the same way.

It looks like the redirection is done after the subshell is forked, so
adding the wait inside the subshell actually works:

$ time bash -c '(echo "subshell \$! = $!"; wait "$!") 2> >(echo "procsub 
pid = $BASHPID"; sleep 2)'
subshell $! = 74756
    procsub pid = 74756
2.014

I get the same behavior with both 4.4.19 and the latest devel snapshot

-- 
Geir Hauge



Re: ~/.profile and ~/.bash_profile aren't executed on login

2017-12-10 Thread Geir Hauge
On Sun, Dec 10, 2017 at 07:22:36PM -0800, Yuri wrote:
> It only calls ~/.profile when it is named 'sh'.

In posix mode, bash only looks for ~/.profile, but when you run it in
non-posix mode, it will look for ~/.bash_profile and ~/.bash_login
first. You probably have a ~/.bash_profile in addition to ~/.profile.

Assuming this is the case, I suggest you merge whatever it contains into
~/.profile, and remove the ~/.bash_profile file.

-- 
Geir Hauge



Re: Trailing newlines disappear

2017-06-08 Thread Geir Hauge
On Fri, Jun 09, 2017 at 03:34:39AM +0700, PePa wrote:
> On 09/06/2560 02:14, Greg Wooledge wrote:
> > Well, it leaves IFS changed, because you didn't revert or unset it,
> > or run the entire thing in a function with local IFS.  Also, I'd use
> > "${MAPFILE[*]}" to reinforce that you are joining an array into a string,
> > rather than expanding the array as a list.
> 
> Thanks for pointing all this out. I settled on:
> mapfile <"$file"; IFS= foo=${MAPFILE[*]} true

Greg already pointed out that this doesn't work.

You can pick one of these instead:

mapfile < "$file"; IFS= foo="${MAPFILE[*]}"; unset -v IFS

or

mapfile < "$file"; printf -v foo %s "${MAPFILE[@]}"

-- 
Geir Hauge



Re: -eq and strings

2017-03-06 Thread Geir Hauge
On Mon, Mar 06, 2017 at 03:31:31PM +0100, Rob la Lau wrote:
> On 06-03-17 15:16, Reuti wrote:
> > if ! expr "$x" : '[[:digit:]]*$' >/dev/null; then echo no; fi
> > 
> > if [ -n "${x//[0-9]/}" ]; then echo no; fi
> 
> True, but regular expressions are usually considered expensive.
> (Must admit I never benchmarked.)
> 
> And I know 1 regex won't considerably slow down my script, but it's
> become a habit to always try and program as light as possible.

If you're counting milliseconds, pattern matching should be slightly
faster than your -eq hack.

is_digit() { [[ -n $1 && $1 != *[![:digit:]]* ]]; }

or the sh variant:

is_digit() { case $1 in ''|*[![:digit:]]*) return 1;; esac; }


See also http://mywiki.wooledge.org/BashFAQ/054

-- 
Geir Hauge



Re: bash "while do echo" can't function correctly

2016-04-12 Thread Geir Hauge
On Wed, Apr 13, 2016 at 10:01:23AM +0800, 何建军 wrote:
> Hi, I use a very simple statement "cat test.txt | while read line; do echo 
> $line; done",  test.txt is very small, no more than 100 lines. but the 
> execution of the statement  paused during process. test.txt is pasted on 
> http://paste.bradleygill.com/index.php?paste_id=1647399 
> desmond.he@xgimi-dev:/studio/desmond.he$ help | head -n 1 GNU bash, version 
> 4.3.11(1)-release (x86_64-pc-linux-gnu) 
> desmond.he@xgimi-dev:/studio/desmond.he$ cat /etc/lsb-release 
> DISTRIB_ID=Ubuntu DISTRIB_RELEASE=14.04 DISTRIB_CODENAME=trusty 
> DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS" Thanks for help~

You didn't quote the expansion of the line variable, so the result of
the expansion is first split into words based on the characters in the
special IFS variable, then each of those words that contain glob
characters (like *, ? , [...]) will be replaced by matching filenames,
if any.

It's the last part that bites you here, since several of your lines
contain * characters. Worse if globstar is enabled, since there's also
** in there, so the "pause" you get is probably bash trying to recurse
through the entire filesystem, which may take a while.

The fix is easy. Just surround the expansion in double quotes, which
prevent word-splitting and pathname expansion.

while read -r line; do echo "$line"; done < test.txt

though printf should be preferred over echo:

while read -r line; do printf '%s\n' "$line"; done < test.txt

-- 
Geir Hauge



read -a ignores upper- and lowercase flags

2016-04-08 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin14.5.0
Compiler: /usr/bin/clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='darwin14.5.0' -DCONF_MACHTYPE='x86_64-apple-darwin14.5.0' 
-DCONF_VENDOR='apple' -DLOCALEDIR='/opt/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include -I./lib  
-I/opt/local/include -pipe -Os -DSSH_SOURCE_BASHRC -arch x86_64
uname output: Darwin MacGeir 14.5.0 Darwin Kernel Version 14.5.0: Tue Sep  1 
21:23:09 PDT 2015; root:xnu-2782.50.1~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin14.5.0

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:

read -ra var  doesn't change the casing of the strings it assigns
when var has been declared with -l or -u.

read without -a, and mapfile both work as expected.

I also tested the latest devel branch to confirm the bug is still
present there.

Repeat-By:

declare -l a b c d
a=( HEllO woRLd )
read -r b <<< "HEllO woRLd"
read -ra c <<< "HEllO woRLd"
mapfile d <<< "HEllO woRLd"
declare -p a b c d

Output:

declare -al a=([0]="hello" [1]="world")
declare -l b="hello world"
declare -al c=([0]="HEllO" [1]="woRLd")
declare -al d=([0]=$'hello world\n')

-- 
Geir Hauge



Re: trap DEBUG and $_

2015-10-12 Thread Geir Hauge
On Mon, Oct 12, 2015 at 07:24:00AM +0200, isabella parakiss wrote:
> On 10/11/15, Dan Stromberg  wrote:
> > Is there a way of outputting a datestamp to shell stderr at the _beginning_
> > of the execution of a command, that won't wipe out $_?
> >
> > I use $_ quite a bit for the last argument to the previous command,
> > interactively.  And I'd like to datestamp all my commands. Datestamping
> > after with $PS1 is easy, but datestamping before is a little harder.
> >
> > I've tried using:
> >
> >function preexec { if tty -s; then echo "$(tput smso)cmd started $(date
> > +%Y\ %a\ %b\ %d\ %r)$(tput rmso)"; fi; }
> >trap preexec DEBUG
> >
> > ...but as you might suspect, I'm finding that $_ is always "preexec" with
> > this enabled.
> >
> > Any suggestions?
> >
> > Thanks!
> >
> trap '__=$_; preexec; : "$__"' DEBUG

And since the preexec function ignores its arguments, it can be
shortened to:

trap 'preexec "$_"' DEBUG

-- 
Geir Hauge



Re: read and env variables + POSIX => SEGFAULT

2015-10-11 Thread Geir Hauge
On Sat, Oct 10, 2015 at 08:01:05PM -0700, Linda Walsh wrote:
> # this is odd: 2vars with content for 2:
> >unset a b
> >a= b= read a b <<< x y
> >declare -p a b
> declare -- a="x"
> declare -- b=""
> 
> # -- where did "y" go?

read a b <<< x y

is the same as

read a b y <<< x

If you escape the space, to make it literal instead of syntactical, you'll get
the expected result:

$ a= b= read a b <<< x\ y
$ declare -p a b
declare -- a="x"
declare -- b="y"



Re: bash displays strange characters after base64 decoding

2015-08-07 Thread Geir Hauge
On Thu, Aug 06, 2015 at 07:45:53PM +0200, Valentin Schmidt wrote:
> Bash displays strange characters (including command prompt) (see attached
> png file) after the execution of the base64 (GNU coreutils 8.21) command
> like described as follows:
> base64 -d base64.txt

Xterm has some escape sequences that switch between a second character
set, where many of the ascii letters become line drawing characters
instead. 

Try the following:

printf %b '\e(0' {a..z} '\n' '\e(B' {a..z} '\n'

This prints the 26 lowercase ascii letters in the second character set,
entered by the sequence ESC ( 0, followed by the same line after
switching back, with the sequence ESC ( B. In a Gnome Terminal on Ubuntu
I get the following output from the above:

▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥
abcdefghijklmnopqrstuvwxyz

Sven Mascheck has written a bit about this fun feature here:
http://www.in-ulm.de/~mascheck/various/alternate_charset/

-- 
Geir Hauge



Re: substitution "read all from fd" silently fails: $(<

2015-07-01 Thread Geir Hauge
On Wed, Jul 01, 2015 at 10:19:10PM +0300, Ilya Basin wrote:
> Hi list.
> 
> Want to read whole stdin into variable.
> Don't want to spawn new processes (cat).
> Don't want to reopen existing fd &0
> 
> First thing I tried: $(<&0)
> It silently returns an empty string.

This type of query is preferably asked at the help-bash list rather than
bug-bash.

 
> # works, but too complex
> [root@okdistr ~]# echo aaa | sudo -u nobody bash -c 'a=; while true; do 
> rc=0; read -N1024 b || rc=$?; a=$a$b; [ $rc = 0 ] || break; done; echo "$a"'
> aaa

IFS= read -rd '' a
printf %s "$a"



Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:00:45AM -0500, Eduardo A. Bustamante López wrote:
> # Here we 'unset ref', which actually unsets 'var'. Then, we assign 'var' to
> # 'ref', but since 'ref' is still a nameref, it instead assigns 'var' to 
> 'var'.
> dualbus@hp:~$ unset ref; ref=var; echo "$ref"; declare -p ref
> var
> declare -n ref="var"
> dualbus@hp:~$ declare -p var
> declare -- var="var"

Ah, that explains it! Mystery solved, and no longer surprising behavior.

-- 
Geir Hauge



Re: unset does not act as expected on namerefs

2015-05-26 Thread Geir Hauge
On Tue, May 26, 2015 at 11:24:57AM -0400, Shawn Wilson wrote:
> On +2015/05/26 11:04:38, Greg Wooledge wrote:
> > On Tue, May 26, 2015 at 10:31:34AM -0400, Shawn Wilson wrote:
> > > swilson@swlap1:~/temp$ bash --version
> > > GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> > > swilson@swlap1:~/temp$ cat t.txt 
> > > $ome text !n a file|
> > > swilson@swlap1:~/temp$ unset t
> > > swilson@swlap1:~/temp$ t=$(< ./t.txt)
> > > swilson@swlap1:~/temp$ echo "$t"
> > > bash: $ome text !n a file|: invalid variable name for name reference
> > > swilson@swlap1:~/temp$ var=foo; declare -n t; t=var; unset t; echo "$t"
> > > bash: $ome text !n a file|: invalid variable name for name reference
> > 
> > As surprising as that is, have a look at "help unset":
> > 
> 
> So current behavior should stand? I would think that unset (with no
> options) should DWIM. This behavior also seemed to surprise most on
> #bash IRC. This is not a bug for lack of documentation or not
> understanding the results after looking at the doc, but a "wow, this
> is surprising - maybe this could behave in a manner so it's not so
> surprising".

The surprising part is that it keeps the -n flag, but partially loses
the nameref ability:

$ var=foo; declare -n ref
$ ref=var
$ printf '%s - ' "$ref"; declare -p ref
foo - declare -n ref="var"
$ unset ref
$ ref=var
$ printf '%s - ' "$ref"; declare -p ref
var - declare -n ref="var"
$ ref=baz
baz - declare -n ref="var"

-- 
Geir Hauge



mapfile segfaults when unsetting array in callback

2015-03-25 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' 
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux shbot 3.13.0-44-generic #73-Ubuntu SMP Tue Dec 16 00:22:43 
UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 33
Release Status: release

Description:
When using mapfile's callback feature, and the callback unsets the
array mapfile is appending to, it segfaults.

Repeat-By:
    callback() { unset MAPFILE; }
(mapfile -c 1 -C callback <<< x)

-- 
Geir Hauge



Re: Does [ -f FILE ] have a bug on testing a symlink ?

2015-02-09 Thread Geir Hauge
2015-02-09 22:00 GMT+01:00 Cheng Rk :

> According this documentation `help test`, I am expecting it should return
> false on anything other than a regular file,
>
> -f FILETrue if file exists and is a regular file.
>
>
> but why it returned true on a symlink to a regular file?
>
> $ [ -f tmp/sym-link ] && echo true
> true
>

The manual has this in addition:

«Unless otherwise specified, primaries that operate on files follow
symbolic links and operate on the target of the link, rather than the link
itself.»

http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions

Probably wouldn't hurt to include that in the help text for the test
builtin as well.

-- 
Geir Hauge


Re: BASH_FUNC__ appearing in environment

2014-11-28 Thread Geir Hauge
2014-11-28 9:43 GMT+01:00 steveT :

> OK - found the functions that are appearing. I was grepping BASH_FUNC__ in
> etc - wrong. The functions are in the /usr/share/bash-completion/completions
> directory - and exist as rcs and sudo  files. The code in those files
> defines functions for _rcs and _sudo respectively. The rcs file contains:
>
> # bash completion for rcs  -*-
> shell-script -*-
>
> _rcs()
> {
>  [--snipp--]
> } &&
> complete -F _rcs ci co rlog rcs rcsdiff
>
> # ex: ts=4 sw=4 et filetype=sh
>
> OK - so that is the code that appears in my environment as BASH_FUNC__rcs
> - now the question is - why - and why does it persist? I am not aware of
> using completion with sudo or rcs - so where/why/how in bash do these
> /usr/share scripts get actioned?
>

The third-party bash-completion package sets a "default completion
function" (see it with complete -p -D; declare -f _completion_loader) that
dynamically loads completions. For instance, if you do

$ rcs TAB

And there is not already a completion loaded for rcs, It will look for
/usr/share/bash-completion/completions/rcs, source it if it finds it, then
use the new completion. This in itself will not cause the function to be
exported. I can only think of two ways of the function being exported, and
that's by

1. specifically exporting it with ''export -f _rcs'' or ''declare -xf _rcs''
2. you happen to run ''set -a'' at some point before the completion
function gets dynamically loaded. When ''set -a'' is in effect, all
variables and functions you define get automatically exported. If the
output of ''echo "$-"'' contains 'a', then it is in effect.

-- 
Geir Hauge


Re: feature: time builtin and file descriptor

2014-10-31 Thread Geir Hauge
2014-10-29 15:09 GMT+01:00 Sami Kerola :
>
> This idea came to my mind while writing a script that runs multiple
> commands, and I simply wanted to know how long they are busy.  I am
> aware alternatives exist, but they can get a bit tricky if one wants to
> have multiple measurements going on simultaneously.  For example:
>
> exec 42>&0
> time --file-descriptor 42
> for i in items; in
> exec 52>&0
> time --file-descriptor 52
> echo "processing $i"
> [...]
> echo "item $i took"
> exec 52>&-
> done
> echo 'all together took:'
> exec 42>&-
>

You could achieve this by using command grouping and TIMEFORMAT:

items=( a b c )
time {
for i in "${items[@]}"; do
time {
echo "processing $i"
sleep "$((RANDOM%5 + 1))"
TIMEFORMAT="item $i took %R seconds"
}
done
TIMEFORMAT='all together took: %R seconds'
}

example output:

processing a
item a took 5.001 seconds
processing b
item b took 1.001 seconds
processing c
item c took 3.001 seconds
all together took: 9.004 seconds


It would be prettier if TIMEFORMAT could be set on invocation of time,
e.g.  TIMEFORMAT='foo took %R seconds' time { ...; } , but time being a
keyword probably makes that hard.

One also has to be careful to sanitize any variables one embeds in
TIMEFORMAT since % characters are special.

-- 
Geir Hauge


Re: Issue with Bash-4.3 Official Patch 27

2014-10-16 Thread Geir Hauge
2014-10-16 15:09 GMT+02:00 Chet Ramey :

> On 10/15/14, 1:49 PM, lorenz.bucher@rohde-schwarz.com wrote:
>
> > But anyway.
> > In my opinion I should trust a shell not violating their own rules and be
> > able to import their own variables.
>
> That's not the issue.  The shell can import variables like that just fine,
> as evidenced by exported functions actually working.  The question is
> whether or not `export' lets you set and export non-identifiers.  It does
> and should not.
>
> > So the % character should be allowed to be used in variable names.
>
> No, shell variable names should continue to be shell identifiers.  You
> can already use `%' (any character, really) in environment variable
> names.


Regardless though, shouldn't source <(declare -xp) work whether or not
the environment contains invalid identifiers? It doesn't at present:

$ env %=% bash -c 'echo "$BASH_VERSION"; source <(declare -xp)'
4.3.30(1)-release
/dev/fd/63: line 1: declare: `%': not a valid identifier

Isn't declare -p output meant to be reusable as shell input?

-- 
Geir Hauge


Re: Issues with exported functions

2014-09-25 Thread Geir Hauge
2014-09-25 10:43 GMT+02:00 Davide Brini :

> I'm not arguing about anything, I just have a question. I understand that
> with the current method used to export functions, it is not possible to
> export a variable to a child whose value begins exactly with the characters
> in question. A quick test seems to confirm that:
>
> $ x='() { echo a; }' bash -c 'echo "$x"'
>
> $ x='()  { echo a; }' bash -c 'echo "$x"'
> ()  { echo a; }
>
>
> So is there a way to be able to export variables with arbitrary values,
> including '() {' ?  Sorry if this has been discussed before.
>

There's the -p flag, but it has other side effects

$ x='() { echo a; }' bash -pc 'echo "$x"'
() { echo a; }

I also dislike that it parses exported functions by default; it violates
the "don't treat data as code" rule. Sure would be nice if there was a
separate flag that only disables parsing of exported functions.

-- 
Geir Hauge


Re: Issues with exported functions

2014-09-25 Thread Geir Hauge
2014-09-25 6:23 GMT+02:00 Linda Walsh :
>
> Maybe exporting fun?
>
>   export fun='() { :;}'
>>  bash -c 'declare -pf fun'
>>
> bash: line 0: declare: fun: not found
> ...
> I've never seen functions created with an assignment.  Is this a
> new syntax in 4.3?
>
> (still in 4.2.43 here)...


Bash has had this feature since "forever"

$ fun='() { echo "$BASH_VERSION";}' bash1 -c fun
1.14.7(1)

Your bash 4.2.43 is no exception, but the way declare's -p and -f
options interact did change in 4.3, so try with just ''declare -f fun''
instead

-- 
Geir Hauge


Re: Segmentation fault bash 4.3.022

2014-08-11 Thread Geir Hauge
2014-08-11 20:47 GMT+02:00 Greg Wooledge :

> On Tue, Aug 12, 2014 at 02:21:18AM +0800, lolilolicon wrote:
> > The following code segfaults when run by bash 4.3.022
> >
> >   set -E
> >   shopt -s lastpipe
> >   trap -- 'true' ERR
> >   true | { true | false; }
>
> I could not reproduce this, on HP-UX or Linux.  I tried from an
> interactive shell, just typing these commands.  Did you use a script?
> Is your bash 4.3.22 from an OS distribution package, or did you compile
> it yourself?  If it's a script, is BASH_ENV set?  Can you still trigger
> the bug with an interactive shell, or with an interactive shell started
> with --norc?
>

I can reproduce this on linux for non-interactive bash (which makes
sense since lastpipe doesn't do much when set -m is in effect), but it's
not limited to 4.3.22, and set -E does not appear to affect the outcome.

$ bash42 -c 'echo "$BASH_VERSION";shopt -s lastpipe; trap -- "printf x"
ERR; true | { true | false; }'
4.2.47(2)-release
xxSegmentation fault

$ bash43 -c 'shopt -s lastpipe; trap -- "printf x" ERR; true | { true |
false; }'
4.3.22(1)-release
xxSegmentation fault

And lastly, in interactive mode
$ set +m; shopt -s lastpipe; trap -- "printf x" ERR; true | { true | false;
}
xxx

Can't quite understand why it would trigger the ERR trap thrice.

-- 
Geir Hauge


Re: sourcing script file from inside a function doesn't work anymore

2014-05-12 Thread Geir Hauge
2014-05-12 14:11 GMT+02:00 Greg Wooledge :

> On Sat, May 10, 2014 at 12:22:40PM +0200, thioroup8 wrote:
> > Now, I source it from inside a function: I obtain following error
> message:
> > bash: declare: tmp: not found
> > I think this problem raises in the particular case of involving array
> > variables definitions inside sourced bash script file...
>
> >   cat << "EOF" > "${file_to_be_sourced}"
> > declare -a tmp='([0]="1" [1]="2")'
> > EOF
>
> The problem is that you are using "declare" within the file-to-be-sourced.
> When you source the file inside a function, Bash runs the declare command
> within the context of the function, where declare has the same meaning as
> "local".  Thus, it makes the variable local to the function.


There really is a bug here, a weird one. Using a simplified script, we
see that this works as expected:

$ source <(printf "declare -a array='(x)'; declare -p array\n")
declare -a array='([0]="x")'


Wrapping it in a function should yield the same output, but doesn't:

$ f() { source <(printf "declare -a array='(x)'; declare -p array\n"); }; f
bash: declare: array: not found


And while declare -p array fails to "find" the array, declare -p
(without a name) does list it:

$ f() { source <(printf "declare -a array='(x)'; declare -p array; declare
-p | grep array= \n"); }; f
bash: declare: array: not found
declare -a array='([0]="x")'


Oddly, the quotes seem to matter; changing array='(x)' to array=(x)
makes it work...

$ f() { source <(printf "declare -a array=(x); declare -p array\n"); }; f
declare -a array='([0]="x")'

-- 
Geir Hauge


Re: ${assoc[key]+set} no longer works.

2014-03-19 Thread Geir Hauge
2014-03-18 16:19 GMT+01:00 Chet Ramey :

> On 3/18/14 5:36 AM, geir.ha...@gmail.com wrote:
>
> > Bash Version: 4.3
> > Patch Level: 0
> > Release Status: release
> >
> > Description:
> > With an associative array, assoc, ${assoc[key]+set} expands to the
> > empty string if the associated value is the empty string.
>
> Thanks for the report.  This was a consequence of a change made back in
> 2011 to expand the value portion of the assignment statement a slightly
> different way.  I've attached a patch to fix it.


Thanks. That patch also makes  [[ -v assoc[x] ]]  return 0. However,
[[ -v assoc ]] returns 1 (which it also does before the patch). Sounds
related to this bug.

-- 
Geir Hauge


${assoc[key]+set} no longer works.

2014-03-18 Thread geir . hauge
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' 
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux gina 3.2.0-59-generic #90-Ubuntu SMP Tue Jan 7 22:43:51 UTC 
2014 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 0
Release Status: release

Description:
With an associative array, assoc, ${assoc[key]+set} expands to the
empty string if the associated value is the empty string.

Repeat-By:
$ declare -A assoc='([x]= [y]="1" )'
$ printf '<%s>\n' "${assoc[x]+x is a key}" "${assoc[y]+y is a key}"
<>





Re: read builtin is not honoring -t argument

2013-12-12 Thread Geir Hauge
2013/12/11 
>
> Description:
> read builtin is not honoring -t argument
>
> Repeat-By:
> Just run 'read -t1' and note that the behavior seems not different
> from simply running 'read' without arguments.
>

What does ''type read'' say? perhaps you have a function or alias by that
name. I can't reproduce it either.

-- 
Geir Hauge


Re: The default value of TIMEFORMAT is incorrectly formatted

2013-11-02 Thread Geir Hauge
2013/11/2 Chet Ramey 

> On 11/1/13, 5:54 PM, Seungbeom Kim wrote:
> > Description:
> >   The default value of TIMEFORMAT is incorrectly formatted:
> >   it is shown as   $'\nreal\t%3lR\nuser\t%3lU\nsys%3lS' in the man
> page,
> >   but it should be $'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'.
>
> Thanks for the report.  This has already been fixed for bash-4.3.
>

I reported this a while back too, and it is changed in the latest devel
branch, but it appears you introduced a different typo:

$'\nreal\t%3lR\nuser\t%3lU\nsys\tt%3lS'

-- 
Geir Hauge


Re: && operator prevents backgrounding over ssh

2013-09-26 Thread Geir Hauge
2013/9/26 Hinrik Örn Sigurðsson 

> The "&&" operator in bash seems to inhibit backgrounding when run over
> ssh. You can try it with the following:
>
>   ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &"
>
> The above command will wait for sleep(1) to finish before returning.
> If it is run without ssh, it returns immediately. Furthermore, other
> shells such as dash and zsh will return immediately regardless of
> whether ssh is used.
>

Probably because it's equivalent to

  { cd /tmp && nohup sleep 10 >/dev/null 2>&1; } &

so the backgrounded process still have stdout and stderr connected to ssh.
This should do what you want:

  cd /tmp && { nohup sleep 10 >/dev/null 2>&2 & }

-- 
Geir Hauge


Re: Inaccurate modification date testing

2013-08-14 Thread Geir Hauge
2013/8/14 Jacek Krüger 

> Bash is innacurate when testing modification dates. It ignores fractions
> of a second. Is it expected? Coreutils test does it properly.
>

Looks like that is fixed in 4.3-alpha

http://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=devel#n554

-- 
Geir Hauge


Typos and other issues with the documentation

2013-08-05 Thread Geir Hauge
Here's a list of a few problems with the documentation I've encountered
lately:


1.  The -n option introduced in 4.3-alpha for the wait builtin is
mistyped as --n in the manual.


2.  A minor typo in the help text for the hash builtin:

$ help hash | grep ' -p'
  -p pathname use PATHNAME is the full pathname of NAME


3.  In the manual, the section on Programmable Completion contains the
following example:

_completion_loader()
{
. "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return
124
}
complete -D -F _completion_loader

If you add a couple of files defining completions for a couple of
commands in /etc/bash_completion.d/ and then run the above example,
completion will stop working for all other commands. I suggest
adding -o default on that complete -D command so that it falls back
on default completion if there's no completion defined for a given
command.

In addition I'd suggest dropping the .sh extension since .sh
suggests the file contains sh code, but it surely will contain bash
specific code. The path already suggests that it will contain bash
completion code, so any extension would be redundant anyway.


4.  The description for TIMEFORMAT in the manual says that if the
variable is not set, bash acts as if it has the value
$'\nreal\t%3lR\nuser\t%3lU\nsys%3lS'. There's missing a \t after sys
there. In the devel branch there's an added backslash, but still
missing the t.


5.  The help text for most (if not all) example/loadables/ get
"polluted" if the text is translated. *.po files generally contain
a block like:

msgid ""
msgstr ""
"Project-Id-Version: bash 4.2\n"
"Report-Msgid-Bugs-To: \n"
...info about who translated it to the language and when etc...

And if ''long_doc'' in ''struct builtin'' contains an empty string,
that empty string gets translated into the above msgstr. So I
    suggest avoiding translating the empty string.


I'm attaching patches against the latest git devel branch for the above
five typos/bugs/suggestions.

-- 
Geir Hauge


0001-wait-n.patch
Description: Binary data


0002-help-hash-use-PATHNAME-is-the-full.patch
Description: Binary data


0003-completion_loader-example.patch
Description: Binary data


0004-Default-TIMEFORMAT.patch
Description: Binary data


0005-Empty-string-translation.patch
Description: Binary data


Invalid extglob causes segfault with help builtin.

2013-08-05 Thread Geir Hauge
Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu'
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux sikozu 3.2.0-40-generic #64-Ubuntu SMP Mon Mar 25
21:22:26 UTC 2013 i686 i686 i386 GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.2
Patch Level: 45
Release Status: release

Description:
One of the side-effects of the latest changes of the help
builtin in the devel release is that ''help "(("'' no longer
shows the help for (( ... )), so I casually threw some asterisks
around it ... and got a segfault. This also happens in bash
4.2.45 and 4.2.25, but not 3.2.48. It only segfaults when
extglob is enabled; probably because it's an incomplete extglob.

Repeat-By:
bash -O extglob -c 'help "*((*"'

-- 
Geir Hauge


Re: Another "set" option?

2013-07-10 Thread Geir Hauge
2013/7/10 Bruce Korb 

> This seems like a lot of obtuse bother:
>
> xtrace_setting=$(
>re=$'\nxtrace[ \t]+on'
>[[ $(set -o) =~ $re ]] && echo ' -x' || echo ' +x')
>
> if there were only some magic like ${BASH_SETTING_XTRACE} or
> xtrace_setting=$(set -q xtrace) or something.  Could we get
> something fairly straight forward for querying set/shopt state?
> Thank you for considering.  Regards, Bruce
>

shopt -qo xtrace && xtrace=1




-- 
Geir Hauge


Re: PS1 multiline with colors

2013-07-09 Thread Geir Hauge
2013/7/9 Dan Douglas 

> Can also give all the debug output %q formatting.
>
> exec {BASH_XTRACEFD}> >(set +x; while IFS= read -r x; do printf %q\\n
> "$x"; done)


Note that {BASH_XTRACEFD}>... won't work in bash 4.2 (or older). It's fixed
for the next release though.

http://lists.gnu.org/archive/html/bug-bash/2012-09/msg6.html

-- 
Geir Hauge


Loadables fail to build in devel branch

2013-05-25 Thread Geir Hauge
The code for the cut and getconf loadables under examples/loadables has
apparently been removed, but the Makefile hasn't been updated accordingly.
See attached patch.

-- 
Geir Hauge


removed_loadables.patch
Description: Binary data


Re: Redirect a backgrounded process' stdout toward COPROC's stdin

2012-06-03 Thread Geir Hauge
2012/6/3 Davide Baldini :
> Description:
> In the following test script I run an elementary coprocess to which the
> echo built-in, run in background, attaches its standard-output:
>
>    #!/bin/bash
>    # TEST 1
>    coproc /bin/sleep 100
>    echo >&${COPROC[1]} &
>
> The script always fails, for no apparent reason, giving the output:
>
>    ./test.sh: line 4: ${COPROC[1]}: Bad file descriptor

The coproc fds are only available in the same shell. The subshell
created with & cannot use them.


> I wonder if the correct syntax should be rather this one (ampersand
> moved before redirection):
>
>    #!/bin/bash
>    # TEST 2
>    coproc /bin/sleep 100
>    echo & >&${COPROC[1]}

This is equivalent to

echo &
>&${COPROC[1]}

& ends the command, so the redirection is not applied to the echo.


See http://wiki.bash-hackers.org/syntax/keywords/coproc

-- 
Geir Hauge



Re: handling of test == by BASH's POSIX mode

2012-05-27 Thread Geir Hauge
2012/5/27 Jon Seymour :
> Is there a reason why bash doesn't treat == as an illegal test
> operator when running in POSIX mode?

POSIX does not say == is not allowed.

POSIX tells you what the shell should at least be able to do. A POSIX
compliant shell can have whatever other features it likes, as long as
the POSIX features are covered.


> This is problematic because use of test == in scripts that should be
> POSIX isn't getting caught when I run them under bash's POSIX mode.
> The scripts then fail when run under dash which seems to be stricter
> about this.

Don't use non-POSIX features in a POSIX script, and you'll be fine.
http://www.opengroup.org/onlinepubs/9699919799/utilities/contents.html

-- 
Geir Hauge



Re: compgen is slow for large numbers of options

2012-03-19 Thread Geir Hauge
2012/3/19 Chet Ramey :
> I will look at optimizing that function, but it's always going to take time
> to plow through 300K when you have to split it into words.  (There's not
> actually any word splitting of consequence happening with your second
> example using the pipeline.)

Letting compgen do the command substitution speeds it up considerably

$ TIMEFORMAT=%R
$ time compgen -W "`seq 1 50`" 1794 >/dev/null
175.253
$ time compgen -W '`seq 1 50`' 1794 >/dev/null
2.347

-- 
Geir Hauge



Re: TAB vs. colon

2011-12-30 Thread Geir Hauge
2011/12/30 

> But sometime we don't type in the path by hand, but instead paste it in
> from elsewhere via the mouse or something. In this case we have to
> painfully add the \   \ stuff by hand before any TAB expansion works.
>

A workaround would be to quote the path. E.g. instead of

ls u

do

ls ''u

-- 
Geir Hauge


Re: '>;' redirection operator [was: [1003.1(2008)/Issue 7 0000530]: Support in-place editing in sed (-iEXTENSION)]

2011-12-22 Thread Geir Hauge
2011/12/22 Bruce Korb 
>
> When the exact opposite is the useful variation?  I.e. keep-on-failure.
> "-i" for sed is simple, understandable and implemented a lot.
>

As far as I know, -i is only implemented with GNU sed and BSD sed, and they
are incompatible, BSD sed's -i takes a mandatory argument, while GNU sed's
-i takes an optional string which must be provided in the same argument.
E.g.

gnused -i.bak sed-script file
bsdsed -i .bak sed-script file

So the only portable way of using sed to "edit" (read: overwrite) a file is
with

sed sed-script file > file.tmp && mv file.tmp file

I'd welcome this >; syntax.

-- 
Geir Hauge


Re: exit status issue

2011-11-18 Thread Geir Hauge
2011/11/17 Dallas Clement 

>
>  Would appreciate any insight you could offer.  Here is my script and
> the strace output for when touch returns 1.
>

Add ''set -x'' at the start of the function and examine the output to see
if it actually runs touch from PATH.

-- 
Geir Hauge


Re: invoke tilde expansion on quoted string

2011-11-12 Thread Geir Hauge
2011/11/12 Chris F.A. Johnson 

> On Fri, 11 Nov 2011, Peng Yu wrote:
>
>> I'm wondering if I already have a string variable, is there a bash
>> native to do tilde expansion on it.
>>
>> var='~/..'
>> cd $var#how to change this line?
>>
>
>  eval "cd $var"
>

I'd avoid eval as that could potentially do more than just expand the
tilde, depending on what other characters the var contains. I'd just
replace the ~ with $HOME using parameter expansion.

cd "${var/#~\//$HOME/}"

-- 
Geir Hauge


Re: bug? {1..3} doesnt' use IFS to separate fields

2011-07-27 Thread Geir Hauge
2011/7/25 Linda Walsh 

>
>
> I know it wasn't designed this way, but it seems like it
> is a bug.
>

The manual says nothing about brace expansion using IFS in any way, so it's
not a bug.


If I do
>  read a b c <<<$(echo {1..3} ); echo "a:$a b:$b c:$c"
> I get:
>  a:1 b:2 c:3
>
> But If I do
>  export IFS=','; read a b c <<<$(echo {1..3} ); echo "a:$a b:$b c:$c"
> I get:
>  a:1 2 3 b: c:
>
> Why should the 2nd case return the wrong answer?
> I.e. shouldn't {1..3} use the IFS to separate arguments?
>

I don't see the usefulness in having brace expansion's behavior changed by
IFS.

If you want {1..3} to turn into the string "1;2;3", assign it to an array,
then print the array that way

array=( {1..3} )
(IFS=';'; echo "${array[*]}") # outputs "1;2;3"
printf -v var '%s;' "${array[@]}"; echo "$var" # outputs "1;2;3;"

-- 
Geir Hauge