Add sleep builtin

2018-08-19 Thread konsolebox
Hi Chet,

The sleep command is often used in loops and using the external sleep
is expensive.  Perhaps we can add the sleep builtin but have it
disabled by default to avoid syntax conflict with the external one.
Users who would want the builtin version can simply run:

[[ BASH_VERSINFO -ge 5 ]] && enable sleep

I have patch attached as file, and also uploaded in
https://github.com/konsolebox/bash/tree/builtin_sleep.

-- 
konsolebox
commit 14203764a208279d213d2b4c0babf52abca6078b
Author: konsolebox 
Date:   Sun Jul 29 07:58:32 2018 +0800

Add sleep as a static builtin that is disabled by default.

diff --git a/Makefile.in b/Makefile.in
index 5fcb44b..b56af30 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -505,7 +505,7 @@ BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
 	   $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
 	   $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
 	   $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def \
-	   $(DEFSRC)/mapfile.def
+	   $(DEFSRC)/mapfile.def $(DEFSRC)/sleep.def
 BUILTIN_C_SRC  = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
 		 $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
 		 $(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
@@ -1650,4 +1650,5 @@ builtins/trap.o: $(DEFSRC)/trap.def
 builtins/type.o: $(DEFSRC)/type.def
 builtins/ulimit.o: $(DEFSRC)/ulimit.def
 builtins/umask.o: $(DEFSRC)/umask.def
+builtins/sleep.o: $(DEFSRC)/sleep.def
 builtins/wait.o: $(DEFSRC)/wait.def
diff --git a/builtins/Makefile.in b/builtins/Makefile.in
index 388ca4e..7514a44 100644
--- a/builtins/Makefile.in
+++ b/builtins/Makefile.in
@@ -143,7 +143,8 @@ DEFSRC =  $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
 	  $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
 	  $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
 	  $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
-	  $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
+	  $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def \
+	  $(srcdir)/sleep.def
 
 STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
 		getopt.h 
@@ -152,7 +153,7 @@ OFILES = builtins.o \
 	alias.o bind.o break.o builtin.o caller.o cd.o colon.o command.o \
 	common.o declare.o echo.o enable.o eval.o evalfile.o \
 	evalstring.o exec.o exit.o fc.o fg_bg.o hash.o help.o history.o \
-	jobs.o kill.o let.o mapfile.o \
+	jobs.o kill.o let.o mapfile.o sleep.o \
 	pushd.o read.o return.o set.o setattr.o shift.o source.o \
 	suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
 	wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
@@ -315,6 +316,7 @@ trap.o: trap.def
 type.o: type.def
 ulimit.o: ulimit.def
 umask.o: umask.def
+sleep.o: sleep.def
 wait.o: wait.def
 getopts.o: getopts.def
 reserved.o: reserved.def
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
index 4f51201..b912d49 100644
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -73,6 +73,7 @@ extern char *strcpy ();
 #define BUILTIN_FLAG_ASSIGNMENT 0x02
 #define BUILTIN_FLAG_LOCALVAR	0x04
 #define BUILTIN_FLAG_POSIX_BUILTIN 0x08
+#define BUILTIN_FLAG_INITIALLY_DISABLED 0x10
 
 #define BASE_INDENT	4
 
@@ -173,11 +174,18 @@ char *posix_builtins[] =
   (char *)NULL
 };
 
+/* Initially disabled builtins */
+char *initially_disabled_builtins[] =
+{
+  "sleep"
+};
+
 /* Forward declarations. */
 static int is_special_builtin ();
 static int is_assignment_builtin ();
 static int is_localvar_builtin ();
 static int is_posix_builtin ();
+static int is_initially_disabled ();
 
 #if !defined (HAVE_RENAME)
 static int rename ();
@@ -831,6 +839,8 @@ builtin_handler (self, defs, arg)
 new->flags |= BUILTIN_FLAG_LOCALVAR;
   if (is_posix_builtin (name))
 new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
+  if (is_initially_disabled (name))
+new->flags |= BUILTIN_FLAG_INITIALLY_DISABLED;
 
   array_add ((char *)new, defs->builtins);
   building_builtin = 1;
@@ -1250,8 +1260,9 @@ write_builtins (defs, structfile, externfile)
 		  else
 		fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
 
-		  fprintf (structfile, "%s%s%s%s%s, %s_doc,\n",
-		"BUILTIN_ENABLED | STATIC_BUILTIN",
+		  fprintf (structfile, "%s%s%s%s%s%s, %s_doc,\n",
+		"STATIC_BUILTIN",
+		(builtin->flags & BUILTIN_FLAG_INITIALLY_DISABLED) ? "" : " | BUILTIN_ENABLED",
 		(builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
 		(builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
 		(builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "",
@@ -1645,6 +1656,13 @@ is_posix_builtin (name)
   return (_find_in_table (name, posix_builtins));
 }
 
+static int
+is_initially_disabled (name)
+ char *name;
+{
+  return (_find_in_table (name, initially_disabled_builtins));
+}
+
 #if !defined (HAVE_RENAME)
 static int
 rename (from, to)
diff --git a/builtins/sleep.def b/builtins/sleep.def
new file mode

Re: Assignment of associative arrays through braces

2018-08-19 Thread konsolebox
On Wed, Aug 1, 2018 at 12:53 AM, konsolebox  wrote:
> On Tue, Jul 31, 2018 at 10:31 PM, Chet Ramey  wrote:
>> On 7/27/18 7:13 PM, konsolebox wrote:
>>> Hi Chet,
>>>
>>> I wonder if you can allow bash to have another syntax to allow simpler
>>> declaration and/or definition of associative arrays.  The changes
>>> needed to have it done seem simple enough, and the only conflict it
>>> makes is a scalar `var={...` assignment, which in my opinion is better
>>> quoted to make it more readable and less questionable from other
>>> syntaxes like brace expansion.  I believe most people intuitively
>>> quotes it, and assignments that start with `{` is fairly rare.
>>
>> So it's syntactic sugar for `declare -gA a; a=( ... )'?
>
> That surely is one of the main goals, but it's not exact.  `declare
> -gA a; a=(...)` would always affect the main global scope.
>
> Example:
>
> $ g() { declare -gA a=([x]=y); }; f() { local -A a=(); g; declare -p
> a; }; declare -A a=([a]=b); f; declare -p a
> declare -A a=()
> declare -A a=([x]="y" )
>
> But as shown in my earlier example, a={...} would only affect the
> nearest scope which was local a={}.
>
> This proposal simply requests an intuitively equivalent simple
> assignment syntax for associative arrays just like a='...' and
> a=(...), with same behavior for scoping.
>
> Maybe we can add another option like -G to have similar effect but
> that's a little different already.  Just allowing a={} would make it
> simpler for every scripter.

By the way, is this rejected?

-- 
konsolebox



Re: Add sleep builtin

2018-08-19 Thread Clint Hepner


> On Aug 19, 2018, at 10:25 AM, konsolebox  wrote:
> 
> Hi Chet,
> 
> The sleep command is often used in loops and using the external sleep
> is expensive.  

Expensive is relative, as the time spent actually sleeping probably dwarfs the 
startup time. If not, you probably want to find an alternative to polling 
anyway.

Clint


Re: Add sleep builtin

2018-08-19 Thread konsolebox
On Mon, Aug 20, 2018 at 12:26 AM, Clint Hepner  wrote:
>
>> On Aug 19, 2018, at 10:25 AM, konsolebox  wrote:
>>
>> Hi Chet,
>>
>> The sleep command is often used in loops and using the external sleep
>> is expensive.
>
> Expensive is relative, as the time spent actually sleeping probably dwarfs 
> the startup time.

Forking is expensive, and collectively is hugely expensive. The
external sleep is also yet another child process to manage.

> If not, you probably want to find an alternative to polling anyway.

Sure, that would be for another solution. Meanwhile I have a patch
which adds about 10 lines of significant runtime code to offer.

-- 
konsolebox



exec/read -s bug?

2018-08-19 Thread Lars Schneider
Hi,

consider this script:

#!/bin/bash
[ "`whoami`" = "root" ] || {
  exec sudo -u root "$0" "$@"
}
read -s -p "enter stuff: " stuff

If I run the script as normal user (not root!) and I abort the "read -s -p"
call with "ctrl-c", then my shell is still in silent mode.

I can consitently replicate that behavior on Ubuntu 14.04.5 LTS (Trusty) 
and BASH 4.3.11(1)-release (x86_64-pc-linux-gnu) as well as BASH 4.3.30.

I also installed BASH 4.4.18 from source and I can replicate the issue.

Can you replicate the issue? 
Is this a known issue?
Do you consider it a bug? 
How would you investigate that further? 
Do you see a workaround for the problem?

I briefly looked into the `builtins/exec.def` and `builtins/read.def` code
and my impression is that `exec` might mess with the `ttsave/ttyrestore` 
stack.

Thanks,
Lars


PS: Before I reached out on the bug bash mailing list I asked for help here:
https://unix.stackexchange.com/questions/463253/why-would-read-s-behaves-differently-than-read-if-killed-with-ctrl-c
 


Re: exec/read -s bug?

2018-08-19 Thread Lars Schneider


> On Aug 19, 2018, at 6:33 PM, Lars Schneider  wrote:
> 
> Hi,
> 
> consider this script:
> 
>   #!/bin/bash
>   [ "`whoami`" = "root" ] || {
> exec sudo -u root "$0" "$@"
>   }
>   read -s -p "enter stuff: " stuff
> 
> If I run the script as normal user (not root!) and I abort the "read -s -p"
> call with "ctrl-c", then my shell is still in silent mode.
> 
> I can consitently replicate that behavior on Ubuntu 14.04.5 LTS (Trusty) 
> and BASH 4.3.11(1)-release (x86_64-pc-linux-gnu) as well as BASH 4.3.30.
> 
> I also installed BASH 4.4.18 from source and I can replicate the issue.

I did a mistake: The problem _was_ fixed with BASH 4.4.18.
Further testing revealed that it is fixed with 4.4. too but not in Bash-4.3 
patch 46.

I think the following item in the release notes corresponds to the problem:

 oo. Fixed a bug that caused bash to not clean up readline's state, including
 the terminal settings, if it received a fatal signal while in a readline()
 call (including `read -e' and `read -s').

Does anyone see a workaround to set the readline state properly
for older BASH versions?

Thanks,
Lars




Re: Add sleep builtin

2018-08-19 Thread Jaren Stangret
Additionally, for simple uses, using:
read -t

Works for pseudo built-in sleep. Not easy to use in subshells, or with any
forks.

On Sun, Aug 19, 2018, 12:12 PM konsolebox  wrote:

> On Mon, Aug 20, 2018 at 12:26 AM, Clint Hepner 
> wrote:
> >
> >> On Aug 19, 2018, at 10:25 AM, konsolebox  wrote:
> >>
> >> Hi Chet,
> >>
> >> The sleep command is often used in loops and using the external sleep
> >> is expensive.
> >
> > Expensive is relative, as the time spent actually sleeping probably
> dwarfs the startup time.
>
> Forking is expensive, and collectively is hugely expensive. The
> external sleep is also yet another child process to manage.
>
> > If not, you probably want to find an alternative to polling anyway.
>
> Sure, that would be for another solution. Meanwhile I have a patch
> which adds about 10 lines of significant runtime code to offer.
>
> --
> konsolebox
>
>


Re: exec/read -s bug?

2018-08-19 Thread Lars Schneider


> On Aug 19, 2018, at 8:45 PM, Lars Schneider  wrote:
> 
> 
>> On Aug 19, 2018, at 6:33 PM, Lars Schneider  wrote:
>> 
>> Hi,
>> 
>> consider this script:
>> 
>>  #!/bin/bash
>>  [ "`whoami`" = "root" ] || {
>>exec sudo -u root "$0" "$@"
>>  }
>>  read -s -p "enter stuff: " stuff
>> 
>> If I run the script as normal user (not root!) and I abort the "read -s -p"
>> call with "ctrl-c", then my shell is still in silent mode.
>> 
>> I can consitently replicate that behavior on Ubuntu 14.04.5 LTS (Trusty) 
>> and BASH 4.3.11(1)-release (x86_64-pc-linux-gnu) as well as BASH 4.3.30.
>> 
>> I also installed BASH 4.4.18 from source and I can replicate the issue.
> 
> I did a mistake: The problem _was_ fixed with BASH 4.4.18.
> Further testing revealed that it is fixed with 4.4. too but not in Bash-4.3 
> patch 46.
> 
> I think the following item in the release notes corresponds to the problem:
> 
> oo. Fixed a bug that caused bash to not clean up readline's state, including
> the terminal settings, if it received a fatal signal while in a readline()
> call (including `read -e' and `read -s').
> 
> Does anyone see a workaround to set the readline state properly
> for older BASH versions?

OK, I found a work around:

[ "`whoami`" = "root" ] || {
  exec sudo -u root "$0" "$@"
}

function finish {
  stty echo echok
}
trap finish EXIT
read -s -p "enter stuff: " stuff
echo "answer: $stuff"

Cheers,
Lars