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 <konsole...@gmail.com> 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 100644 index 0000000..4054e87 --- /dev/null +++ b/builtins/sleep.def @@ -0,0 +1,71 @@ +This file is sleep.def, from which is created sleep.c. +It implements the builtin "sleep" in Bash. + +Copyright (C) 1987-2018 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Bash. If not, see <http://www.gnu.org/licenses/>. + +$PRODUCES sleep.c + +$BUILTIN sleep +$FUNCTION sleep_builtin +$SHORT_DOC sleep seconds[.fraction] +Suspend execution for approximately SECONDS[.FRACTION] seconds. + +This builtin is disabled by default. Enable it with `enable sleep'. + +Exit Status: +Returns success unless aborted. +$END + +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include <sys/types.h> +# endif +# include <unistd.h> +#endif + +#include "../bashansi.h" +#include "../bashintl.h" +#include "../shell.h" +#include "common.h" + +int +sleep_builtin (list) + WORD_LIST *list; +{ + long sec, usec; + + if (list && list->word && ISOPTION (list->word->word, '-')) + list = list->next; + + if (!list) + { + builtin_usage (); + return (EX_USAGE); + } + + if (uconvert (list->word->word, &sec, &usec)) + { + fsleep (sec, usec); + return (EXECUTION_SUCCESS); + } + + builtin_error ("%s: bad sleep interval", list->word->word); + return (EXECUTION_FAILURE); +}