import bash-5.2.26-4.el10

cs10 imports/cs10/bash-5.2.26-4.el10
MSVSphere Packaging Team 4 months ago
commit 39c85ea8ca
Signed by: sys_gitsync
GPG Key ID: B2B0B9F29E528FE8

@ -0,0 +1,2 @@
a799460be16c01aeab492b9aa88f5eb7f35c1b9b SOURCES/bash-5.2.tar.gz
993ce9aa151dd3b3cb7b2f8eb6ff05f548cbba7f SOURCES/bash-5.2.tar.gz.sig

2
.gitignore vendored

@ -0,0 +1,2 @@
SOURCES/bash-5.2.tar.gz
SOURCES/bash-5.2.tar.gz.sig

@ -0,0 +1,12 @@
diff -up bash-3.2/config-top.h.profile bash-3.2/config-top.h
--- bash-3.2/config-top.h.profile 2008-07-17 13:35:39.000000000 +0200
+++ bash-3.2/config-top.h 2008-07-17 13:42:18.000000000 +0200
@@ -26,6 +26,8 @@
what POSIX.2 specifies. */
#define CONTINUE_AFTER_KILL_ERROR
+#define NON_INTERACTIVE_LOGIN_SHELLS
+
/* Define BREAK_COMPLAINS if you want the non-standard, but useful
error messages about `break' and `continue' out of context. */
#define BREAK_COMPLAINS

@ -0,0 +1,215 @@
diff --git a/config.h.in b/config.h.in
index ab316d4..11d1d68 100644
--- a/config.h.in
+++ b/config.h.in
@@ -775,6 +775,9 @@
/* Define if you have the pselect function. */
#undef HAVE_PSELECT
+/* Define if you have the pread function. */
+#undef HAVE_PREAD
+
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
@@ -981,6 +984,9 @@
/* Define if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
/* Define if you have the <grp.h> header file. */
#undef HAVE_GRP_H
diff --git a/configure.ac b/configure.ac
index 2fe3e7d..f1b7f1b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -827,7 +827,7 @@ dnl checks for system calls
AC_CHECK_FUNCS(dup2 eaccess fcntl getdtablesize getentropy getgroups \
gethostname getpagesize getpeername getrandom getrlimit \
getrusage gettimeofday kill killpg lstat pselect readlink \
- select setdtablesize setitimer tcgetpgrp uname ulimit waitpid)
+ select setdtablesize setitimer tcgetpgrp uname ulimit waitpid pread)
AC_REPLACE_FUNCS(rename)
dnl checks for c library functions
diff --git a/execute_cmd.c b/execute_cmd.c
index d2a0dd7..d2555ad 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -41,6 +41,10 @@
# include <unistd.h>
#endif
+#ifdef HAVE_ELF_H
+# include <elf.h>
+#endif
+
#include "posixtime.h"
#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
@@ -5832,6 +5836,14 @@ shell_execve (command, args, env)
{
/* The file has the execute bits set, but the kernel refuses to
run it for some reason. See why. */
+#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
+ int fd = open (command, O_RDONLY);
+
+ if (fd >= 0)
+ sample_len = read (fd, sample, sizeof (sample));
+ else
+ sample_len = -1;
+#endif
#if defined (HAVE_HASH_BANG_EXEC)
READ_SAMPLE_BUF (command, sample, sample_len);
if (sample_len > 0)
@@ -5841,6 +5853,7 @@ shell_execve (command, args, env)
char *interp;
int ilen;
+ close (fd);
interp = getinterp (sample, sample_len, (int *)NULL);
ilen = strlen (interp);
errno = i;
@@ -5856,7 +5869,138 @@ shell_execve (command, args, env)
return (EX_NOEXEC);
}
#endif
- errno = i;
+#if defined (HAVE_ELF_H)
+ if (i == ENOENT
+ && sample_len > EI_NIDENT
+ && memcmp (sample, ELFMAG, SELFMAG) == 0)
+ {
+ off_t offset = -1;
+
+ /* It is an ELF file. Now determine whether it is dynamically
+ linked and if yes, get the offset of the interpreter
+ string. */
+ if (sample[EI_CLASS] == ELFCLASS32
+ && sample_len > sizeof (Elf32_Ehdr))
+ {
+ Elf32_Ehdr ehdr;
+ Elf32_Phdr *phdr;
+ int nphdr;
+
+ /* We have to copy the data since the sample buffer
+ might not be aligned correctly to be accessed as
+ an Elf32_Ehdr struct. */
+ memcpy (&ehdr, sample, sizeof (Elf32_Ehdr));
+
+ nphdr = ehdr.e_phnum;
+ phdr = (Elf32_Phdr *) malloc (nphdr * ehdr.e_phentsize);
+ if (phdr != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
+ ehdr.e_phoff);
+#else
+ if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
+ sample_len = read (fd, phdr,
+ nphdr * ehdr.e_phentsize);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == nphdr * ehdr.e_phentsize)
+ while (nphdr-- > 0)
+ if (phdr[nphdr].p_type == PT_INTERP)
+ {
+ offset = phdr[nphdr].p_offset;
+ break;
+ }
+ free (phdr);
+ }
+ }
+ else if (sample[EI_CLASS] == ELFCLASS64
+ && sample_len > sizeof (Elf64_Ehdr))
+ {
+ Elf64_Ehdr ehdr;
+ Elf64_Phdr *phdr;
+ int nphdr;
+
+ /* We have to copy the data since the sample buffer
+ might not be aligned correctly to be accessed as
+ an Elf64_Ehdr struct. */
+ memcpy (&ehdr, sample, sizeof (Elf64_Ehdr));
+
+ nphdr = ehdr.e_phnum;
+ phdr = (Elf64_Phdr *) malloc (nphdr * ehdr.e_phentsize);
+ if (phdr != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
+ ehdr.e_phoff);
+#else
+ if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
+ sample_len = read (fd, phdr,
+ nphdr * ehdr.e_phentsize);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == nphdr * ehdr.e_phentsize)
+ while (nphdr-- > 0)
+ if (phdr[nphdr].p_type == PT_INTERP)
+ {
+ offset = phdr[nphdr].p_offset;
+ break;
+ }
+ free (phdr);
+ }
+ }
+
+ if (offset != -1)
+ {
+ size_t maxlen = 0;
+ size_t actlen = 0;
+ char *interp = NULL;
+
+ do
+ {
+ if (actlen == maxlen)
+ {
+ char *newinterp = realloc (interp, maxlen += 200);
+ if (newinterp == NULL)
+ {
+ actlen = 0;
+ break;
+ }
+ interp = newinterp;
+
+#ifdef HAVE_PREAD
+ actlen = pread (fd, interp, maxlen, offset);
+#else
+ if (lseek (fd, offset, SEEK_SET) != -1)
+ actlen = read (fd, interp, maxlen);
+ else
+ actlen = -1;
+#endif
+ }
+ }
+ while (actlen > 0 && memchr (interp, '\0', actlen) == NULL);
+
+ if (actlen > 0)
+ {
+ close (fd);
+ errno = i;
+ sys_error ("%s: %s: bad ELF interpreter", command,
+ interp);
+ free (interp);
+ return (EX_NOEXEC);
+ }
+
+ free (interp);
+ }
+ }
+#endif
+#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
+ close (fd);
+#endif
+
+ errno = i;
file_error (command);
}
return (last_command_exit_value);

@ -0,0 +1,10 @@
--- bash-2.05b/builtins/Makefile.in.debuginfo 2003-03-25 17:25:21.000000000 +0000
+++ bash-2.05b/builtins/Makefile.in 2003-03-25 17:25:49.000000000 +0000
@@ -93,7 +93,6 @@
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
$(CC) -c $(CCFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
- $(RM) $*.c
# How to make a .c file from a .def file.
.def.c:

@ -0,0 +1,12 @@
diff --git a/aclocal.m4 b/aclocal.m4
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1324,7 +1324,7 @@ main()
wait(&status);
exit(ok ? 0 : 5);
}
-]])], [bash_cv_pgrp_pipe=no], [bash_cv_pgrp_pipe=yes],
+]])], [bash_cv_pgrp_pipe=yes], [bash_cv_pgrp_pipe=yes],
[AC_MSG_WARN(cannot check pgrp synchronization if cross compiling -- defaulting to no)
bash_cv_pgrp_pipe=no]
)])

@ -0,0 +1,13 @@
diff --git a/config-top.h b/config-top.h
index e5cc147..f5e0a52 100644
--- a/config-top.h
+++ b/config-top.h
@@ -106,7 +106,7 @@
sshd and source the .bashrc if so (like the rshd behavior). This checks
for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment,
which can be fooled under certain not-uncommon circumstances. */
-/* #define SSH_SOURCE_BASHRC */
+#define SSH_SOURCE_BASHRC
/* Define if you want the case-toggling operators (~[~]) and the
`capcase' variable attribute (declare -c). */

@ -0,0 +1,154 @@
diff -up bash-4.0/execute_cmd.c.nobits bash-4.0/execute_cmd.c
--- bash-4.0/execute_cmd.c.nobits 2009-08-11 11:53:38.000000000 +0200
+++ bash-4.0/execute_cmd.c 2009-08-14 16:18:18.000000000 +0200
@@ -4747,6 +4747,7 @@ shell_execve (command, args, env)
&& memcmp (sample, ELFMAG, SELFMAG) == 0)
{
off_t offset = -1;
+ int dynamic_nobits = 0;
/* It is an ELF file. Now determine whether it is dynamically
linked and if yes, get the offset of the interpreter
@@ -4756,13 +4757,61 @@ shell_execve (command, args, env)
{
Elf32_Ehdr ehdr;
Elf32_Phdr *phdr;
- int nphdr;
+ Elf32_Shdr *shdr;
+ int nphdr, nshdr;
/* We have to copy the data since the sample buffer
might not be aligned correctly to be accessed as
an Elf32_Ehdr struct. */
memcpy (&ehdr, sample, sizeof (Elf32_Ehdr));
+ nshdr = ehdr.e_shnum;
+ shdr = (Elf32_Shdr *) malloc (nshdr * ehdr.e_shentsize);
+
+ if (shdr != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, shdr, nshdr * ehdr.e_shentsize,
+ ehdr.e_shoff);
+#else
+ if (lseek (fd, ehdr.e_shoff, SEEK_SET) != -1)
+ sample_len = read (fd, shdr,
+ nshdr * ehdr.e_shentsize);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == nshdr * ehdr.e_shentsize)
+ {
+ char *strings = (char *) malloc (shdr[ehdr.e_shstrndx].sh_size);
+ if (strings != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, strings,
+ shdr[ehdr.e_shstrndx].sh_size,
+ shdr[ehdr.e_shstrndx].sh_offset);
+#else
+ if (lseek (fd, shdr[ehdr.e_shstrndx].sh_offset,
+ SEEK_SET) != -1)
+ sample_len = read (fd, strings,
+ shdr[ehdr.e_shstrndx].sh_size);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == shdr[ehdr.e_shstrndx].sh_size)
+ while (nshdr-- > 0)
+ if (strcmp (strings + shdr[nshdr].sh_name,
+ ".interp") == 0 &&
+ shdr[nshdr].sh_type == SHT_NOBITS)
+ {
+ dynamic_nobits++;
+ break;
+ }
+ free (strings);
+ }
+ }
+ free (shdr);
+ }
+
nphdr = ehdr.e_phnum;
phdr = (Elf32_Phdr *) malloc (nphdr * ehdr.e_phentsize);
if (phdr != NULL)
@@ -4792,13 +4841,60 @@ shell_execve (command, args, env)
{
Elf64_Ehdr ehdr;
Elf64_Phdr *phdr;
- int nphdr;
+ Elf64_Shdr *shdr;
+ int nphdr, nshdr;
/* We have to copy the data since the sample buffer
might not be aligned correctly to be accessed as
an Elf64_Ehdr struct. */
memcpy (&ehdr, sample, sizeof (Elf64_Ehdr));
+ nshdr = ehdr.e_shnum;
+ shdr = (Elf64_Shdr *) malloc (nshdr * ehdr.e_shentsize);
+ if (shdr != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, shdr, nshdr * ehdr.e_shentsize,
+ ehdr.e_shoff);
+#else
+ if (lseek (fd, ehdr.e_shoff, SEEK_SET) != -1)
+ sample_len = read (fd, shdr,
+ nshdr * ehdr.e_shentsize);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == nshdr * ehdr.e_shentsize)
+ {
+ char *strings = (char *) malloc (shdr[ehdr.e_shstrndx].sh_size);
+ if (strings != NULL)
+ {
+#ifdef HAVE_PREAD
+ sample_len = pread (fd, strings,
+ shdr[ehdr.e_shstrndx].sh_size,
+ shdr[ehdr.e_shstrndx].sh_offset);
+#else
+ if (lseek (fd, shdr[ehdr.e_shstrndx].sh_offset,
+ SEEK_SET) != -1)
+ sample_len = read (fd, strings,
+ shdr[ehdr.e_shstrndx].sh_size);
+ else
+ sample_len = -1;
+#endif
+ if (sample_len == shdr[ehdr.e_shstrndx].sh_size)
+ while (nshdr-- > 0)
+ if (strcmp (strings + shdr[nshdr].sh_name,
+ ".interp") == 0 &&
+ shdr[nshdr].sh_type == SHT_NOBITS)
+ {
+ dynamic_nobits++;
+ break;
+ }
+ free (strings);
+ }
+ }
+ free (shdr);
+ }
+
nphdr = ehdr.e_phnum;
phdr = (Elf64_Phdr *) malloc (nphdr * ehdr.e_phentsize);
if (phdr != NULL)
@@ -4858,8 +4954,15 @@ shell_execve (command, args, env)
{
close (fd);
errno = i;
- sys_error ("%s: %s: bad ELF interpreter", command,
- interp);
+ if (dynamic_nobits > 0)
+ {
+ sys_error ("%s: bad ELF interpreter", command);
+ }
+ else
+ {
+ sys_error ("%s: %s: bad ELF interpreter", command,
+ interp);
+ }
free (interp);
return (EX_NOEXEC);
}

@ -0,0 +1,12 @@
diff -up bash-4.1/config-top.h.broken_pipe bash-4.1/config-top.h
--- bash-4.1/config-top.h.broken_pipe 2011-01-06 18:01:30.000000000 +0100
+++ bash-4.1/config-top.h 2011-01-06 18:02:14.000000000 +0100
@@ -51,7 +51,7 @@
/* Define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS if you don't want builtins
like `echo' and `printf' to report errors when output does not succeed
due to EPIPE. */
-/* #define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS */
+#define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS
/* The default value of the PATH variable. */
#ifndef DEFAULT_PATH_VALUE

@ -0,0 +1,24 @@
diff --git a/examples/loadables/Makefile.in b/examples/loadables/Makefile.in
--- a/examples/loadables/Makefile.in
+++ b/examples/loadables/Makefile.in
@@ -59,7 +59,7 @@ host_cpu = @host_cpu@
host_vendor = @host_vendor@
STYLE_CFLAGS = @STYLE_CFLAGS@
-CFLAGS = @CFLAGS@
++CFLAGS = -O2 -g
LOCAL_CFLAGS = @LOCAL_CFLAGS@
DEFS = @DEFS@
LOCAL_DEFS = @LOCAL_DEFS@
diff --git a/examples/loadables/perl/Makefile.in b/examples/loadables/perl/Makefile.in
--- a/examples/loadables/perl/Makefile.in
+++ b/examples/loadables/perl/Makefile.in
@@ -42,7 +42,7 @@ SHELL = @MAKE_SHELL@
PERL5 = perl5
-CFLAGS = @CFLAGS@
+CFLAGS = -O2 -g
#
# These values are generated for configure by ${topdir}/support/shobj-conf.

@ -0,0 +1,103 @@
diff --git a/execute_cmd.c b/execute_cmd.c
index a988400..412128c 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -5760,7 +5760,7 @@ shell_execve (command, args, env)
Elf32_Ehdr ehdr;
Elf32_Phdr *phdr;
Elf32_Shdr *shdr;
- int nphdr, nshdr;
+ Elf32_Half nphdr, nshdr;
/* We have to copy the data since the sample buffer
might not be aligned correctly to be accessed as
@@ -5768,12 +5768,12 @@ shell_execve (command, args, env)
memcpy (&ehdr, sample, sizeof (Elf32_Ehdr));
nshdr = ehdr.e_shnum;
- shdr = (Elf32_Shdr *) malloc (nshdr * ehdr.e_shentsize);
+ shdr = (Elf32_Shdr *) malloc ((size_t)nshdr * (size_t)ehdr.e_shentsize);
if (shdr != NULL)
{
#ifdef HAVE_PREAD
- sample_len = pread (fd, shdr, nshdr * ehdr.e_shentsize,
+ sample_len = pread (fd, shdr, (size_t)nshdr * (size_t)ehdr.e_shentsize,
ehdr.e_shoff);
#else
if (lseek (fd, ehdr.e_shoff, SEEK_SET) != -1)
@@ -5815,11 +5815,11 @@ shell_execve (command, args, env)
}
nphdr = ehdr.e_phnum;
- phdr = (Elf32_Phdr *) malloc (nphdr * ehdr.e_phentsize);
+ phdr = (Elf32_Phdr *) malloc ((size_t)nphdr * (size_t)ehdr.e_phentsize);
if (phdr != NULL)
{
#ifdef HAVE_PREAD
- sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
+ sample_len = pread (fd, phdr, (size_t)nphdr * (size_t)ehdr.e_phentsize,
ehdr.e_phoff);
#else
if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
@@ -5844,7 +5844,7 @@ shell_execve (command, args, env)
Elf64_Ehdr ehdr;
Elf64_Phdr *phdr;
Elf64_Shdr *shdr;
- int nphdr, nshdr;
+ Elf32_Half nphdr, nshdr;
/* We have to copy the data since the sample buffer
might not be aligned correctly to be accessed as
@@ -5852,11 +5852,11 @@ shell_execve (command, args, env)
memcpy (&ehdr, sample, sizeof (Elf64_Ehdr));
nshdr = ehdr.e_shnum;
- shdr = (Elf64_Shdr *) malloc (nshdr * ehdr.e_shentsize);
+ shdr = (Elf64_Shdr *) malloc ((size_t)nshdr * (size_t)ehdr.e_shentsize);
if (shdr != NULL)
{
#ifdef HAVE_PREAD
- sample_len = pread (fd, shdr, nshdr * ehdr.e_shentsize,
+ sample_len = pread (fd, shdr, (size_t)nshdr * (size_t)ehdr.e_shentsize,
ehdr.e_shoff);
#else
if (lseek (fd, ehdr.e_shoff, SEEK_SET) != -1)
@@ -5898,11 +5898,11 @@ shell_execve (command, args, env)
}
nphdr = ehdr.e_phnum;
- phdr = (Elf64_Phdr *) malloc (nphdr * ehdr.e_phentsize);
+ phdr = (Elf64_Phdr *) malloc ((size_t)nphdr * (size_t)ehdr.e_phentsize);
if (phdr != NULL)
{
#ifdef HAVE_PREAD
- sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
+ sample_len = pread (fd, phdr, (size_t)nphdr * (size_t)ehdr.e_phentsize,
ehdr.e_phoff);
#else
if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
@@ -5924,8 +5924,8 @@ shell_execve (command, args, env)
if (offset != -1)
{
- size_t maxlen = 0;
- size_t actlen = 0;
+ ssize_t maxlen = 0;
+ ssize_t actlen = 0;
char *interp = NULL;
do
@@ -5974,7 +5974,8 @@ shell_execve (command, args, env)
}
#endif
#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
- close (fd);
+ if (fd >= 0)
+ close (fd);
#endif
errno = i;
--
2.17.2

@ -0,0 +1,12 @@
diff -up bash-4.1/doc/bash.1.manpage_trap bash-4.1/doc/bash.1
--- bash-4.1/doc/bash.1.manpage_trap 2012-08-28 10:06:00.561999092 +0200
+++ bash-4.1/doc/bash.1 2012-08-28 10:06:24.225304505 +0200
@@ -9251,7 +9251,7 @@ being inverted via
These are the same conditions obeyed by the \fBerrexit\fP (\fB\-e\fP) option.
.if t .sp 0.5
.if n .sp 1
-Signals ignored upon entry to the shell cannot be trapped or reset.
+Signals ignored upon entry to the shell cannot be trapped, reset or listed.
Trapped signals that are not being ignored are reset to their original
values in a subshell or subshell environment when one is created.
The return status is false if any

@ -0,0 +1,41 @@
diff --git a/config-top.h b/config-top.h
index 026d4a4..cb0e002 100644
--- a/config-top.h
+++ b/config-top.h
@@ -92,7 +92,7 @@
/* #define SYS_BASHRC "/etc/bash.bashrc" */
/* System-wide .bash_logout for login shells. */
-/* #define SYS_BASH_LOGOUT "/etc/bash.bash_logout" */
+#define SYS_BASH_LOGOUT "/etc/bash.bash_logout"
/* Define this to make non-interactive shells begun with argv[0][0] == '-'
run the startup files when not in posix mode. */
diff --git a/doc/bash.1 b/doc/bash.1
index 04ce845..bfde55e 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -335,8 +335,8 @@ option may be used when the shell is started to inhibit this behavior.
When an interactive login shell exits,
or a non-interactive login shell executes the \fBexit\fP builtin command,
.B bash
-reads and executes commands from the file \fI~/.bash_logout\fP, if it
-exists.
+reads and executes commands from the files \fI~/.bash_logout\fP
+and \fI/etc/bash.bash_logout\fP, if the files exists.
.PP
When an interactive shell that is not a login shell is started,
.B bash
@@ -10558,6 +10558,9 @@ The \fBbash\fP executable
.FN /etc/profile
The systemwide initialization file, executed for login shells
.TP
+.FN /etc/bash.bash_logout
+The systemwide login shell cleanup file, executed when a login shell exits
+.TP
.FN ~/.bash_profile
The personal initialization file, executed for login shells
.TP
--
2.9.3

@ -0,0 +1,14 @@
diff -up bash-4.2/variables.h.size_type bash-4.2/variables.h
--- bash-4.2/variables.h.size_type 2012-11-29 10:33:25.109036844 +0100
+++ bash-4.2/variables.h 2012-11-29 10:46:12.718530162 +0100
@@ -95,8 +95,8 @@ typedef struct variable {
typedef struct _vlist {
SHELL_VAR **list;
- int list_size; /* allocated size */
- int list_len; /* current number of entries */
+ size_t list_size; /* allocated size */
+ size_t list_len; /* current number of entries */
} VARLIST;
/* The various attributes that a given variable can have. */

@ -0,0 +1,12 @@
diff --git a/lib/readline/rlconf.h b/lib/readline/rlconf.h
--- a/lib/readline/rlconf.h
+++ b/lib/readline/rlconf.h
@@ -64,7 +64,7 @@
/* Define this if you want to enable code that talks to the Linux kernel
tty auditing system. */
-/* #define ENABLE_TTY_AUDIT_SUPPORT */
+#define ENABLE_TTY_AUDIT_SUPPORT
/* Defaults for the various editing mode indicators, inserted at the beginning
of the last (maybe only) line of the prompt if show-mode-in-prompt is on */

@ -0,0 +1,15 @@
diff --git a/doc/bash.1 b/doc/bash.1
index 6e8aebb..e846e68 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -10333,6 +10333,7 @@ and
which are in 512-byte increments.
The return status is 0 unless an invalid option or argument is supplied,
or an error occurs while setting a new limit.
+In POSIX Mode 512-byte blocks are used for the `-c' and `-f' options.
.RE
.TP
\fBumask\fP [\fB\-p\fP] [\fB\-S\fP] [\fImode\fP]
--
2.9.3

@ -0,0 +1,13 @@
diff --git a/locale.c b/locale.c
index 17ccc58..a6c07a3 100644
--- a/locale.c
+++ b/locale.c
@@ -78,8 +78,6 @@ set_default_locale ()
{
#if defined (HAVE_SETLOCALE)
default_locale = setlocale (LC_ALL, "");
- if (default_locale)
- default_locale = savestring (default_locale);
#else
default_locale = savestring ("C");
#endif /* HAVE_SETLOCALE */

@ -0,0 +1,42 @@
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -4255,7 +4255,8 @@ xparse_dolparen (base, string, indp, flags)
save_parser_state (&ps);
save_input_line_state (&ls);
-
+ /* avoid echoing every substitution again */
+ echo_input_at_read = 0;
#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
pushed_string_list = (STRING_SAVER *)NULL;
#endif
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -10222,6 +10222,7 @@ param_expand (string, sindex, quoted, expanded_something,
WORD_LIST *list, *l;
WORD_DESC *tdesc, *ret;
int tflag, nullarg;
+ int old_echo_input;
/*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
zindex = *sindex;
@@ -10614,6 +10615,9 @@ arithsub:
}
comsub:
+ old_echo_input = echo_input_at_read;
+ /* avoid echoing every substitution again */
+ echo_input_at_read = 0;
if (pflags & PF_NOCOMSUB)
/* we need zindex+1 because string[zindex] == RPAREN */
temp1 = substring (string, *sindex, zindex+1);
@@ -10626,6 +10630,7 @@ comsub:
}
FREE (temp);
temp = temp1;
+ echo_input_at_read = old_echo_input;
break;
/* Do POSIX.2d9-style arithmetic substitution. This will probably go

@ -0,0 +1,15 @@
diff --git a/Makefile.in b/Makefile.in
index a1f9483..24c646a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -800,7 +800,6 @@ install: .made installdirs
infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
-( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
-( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
- -( cd $(LOADABLES_DIR) && $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
install-strip:
$(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
--
2.9.3

@ -0,0 +1,13 @@
diff --git a/doc/bash.1 b/doc/bash.1
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -10726,6 +10726,9 @@ If set, the shell automatically closes file descriptors assigned using the
.el above)
instead of leaving them open when the command completes.
.TP 8
+.B syslog_history
+If set, command history is logged to syslog.
+.TP 8
.B xpg_echo
If set, the \fBecho\fP builtin expands backslash-escape sequences
by default.

@ -0,0 +1,24 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 0
+#define PATCHLEVEL 1
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
index d9feabca..93b91606 100644
--- a/subst.c
+++ b/subst.c
@@ -10857,7 +10857,7 @@ expand_array_subscript (string, sindex, quoted, flags)
exp = substring (string, si+1, ni);
t = expand_subscript_string (exp, quoted & ~(Q_ARITH|Q_DOUBLE_QUOTES));
free (exp);
- exp = sh_backslash_quote (t, abstab, 0);
+ exp = t ? sh_backslash_quote (t, abstab, 0) : savestring ("");
free (t);
slen = STRLEN (exp);

@ -0,0 +1,41 @@
diff --git a/general.c b/general.c
--- a/general.c
+++ b/general.c
@@ -683,21 +683,20 @@ check_binary_file (sample, sample_len)
int sample_len;
{
register int i;
+ int nline;
unsigned char c;
if (sample_len >= 4 && sample[0] == 0x7f && sample[1] == 'E' && sample[2] == 'L' && sample[3] == 'F')
return 1;
/* Generally we check the first line for NULs. If the first line looks like
- a `#!' interpreter specifier, we just look for NULs anywhere in the
- buffer. */
- if (sample[0] == '#' && sample[1] == '!')
- return (memchr (sample, '\0', sample_len) != NULL);
+ a `#!' interpreter specifier, we look for NULs in the first two lines. */
+ nline = (sample[0] == '#' && sample[1] == '!') ? 2 : 1;
for (i = 0; i < sample_len; i++)
{
c = sample[i];
- if (c == '\n')
+ if (c == '\n' && --nline == 0)
return (0);
if (c == '\0')
return (1);
diff --git a/patchlevel.h b/patchlevel.h
index e59027ac..9ddc79f7 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 9
+#define PATCHLEVEL 10
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,25 @@
diff --git a/builtins/read.def b/builtins/read.def
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -167,6 +167,9 @@ reset_timeout ()
/* Cancel alarm before restoring signal handler. */
if (read_timeout)
shtimer_clear (read_timeout);
+#if defined (READLINE)
+ rl_clear_timeout ();
+#endif
read_timeout = 0;
}
diff --git a/patchlevel.h b/patchlevel.h
index 9ddc79f7..9ff902a0 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 10
+#define PATCHLEVEL 11
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,268 @@
diff --git a/builtins/common.h b/builtins/common.h
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -257,6 +257,10 @@ extern int print_shift_error;
extern int expand_once_flag;
#endif
+#if defined (EXTENDED_GLOB)
+extern int extglob_flag;
+#endif
+
extern int expaliases_flag;
/* variables from source.def */
diff --git a/builtins/shopt.def b/builtins/shopt.def
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -149,6 +149,11 @@ static int shopt_set_complete_direxpand PARAMS((char *, int));
static int set_assoc_expand PARAMS((char *, int));
#endif
+#if defined (EXTENDED_GLOB)
+int extglob_flag = EXTGLOB_DEFAULT;
+static int shopt_set_extglob PARAMS((char *, int));
+#endif
+
int expaliases_flag = 0;
static int shopt_set_expaliases PARAMS((char *, int));
@@ -206,7 +211,7 @@ static struct {
{ "extdebug", &debugging_mode, shopt_set_debug_mode },
#endif
#if defined (EXTENDED_GLOB)
- { "extglob", &extended_glob, (shopt_set_func_t *)NULL },
+ { "extglob", &extglob_flag, shopt_set_extglob },
#endif
{ "extquote", &extended_quote, (shopt_set_func_t *)NULL },
{ "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL },
@@ -377,7 +382,7 @@ reset_shopt_options ()
#endif
#if defined (EXTENDED_GLOB)
- extended_glob = EXTGLOB_DEFAULT;
+ extended_glob = extglob_flag = EXTGLOB_DEFAULT;
#endif
#if defined (ARRAY_VARS)
@@ -643,6 +648,17 @@ shopt_set_expaliases (option_name, mode)
return 0;
}
+#if defined (EXTENDED_GLOB)
+static int
+shopt_set_extglob (option_name, mode)
+ char *option_name;
+ int mode;
+{
+ extended_glob = extglob_flag;
+ return 0;
+}
+#endif
+
#if defined (READLINE)
static int
shopt_enable_hostname_completion (option_name, mode)
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -3990,13 +3990,11 @@ execute_cond_node (cond)
else
#endif /* COND_REGEXP */
{
- int oe;
- oe = extended_glob;
extended_glob = 1;
result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE)
? EXECUTION_SUCCESS
: EXECUTION_FAILURE;
- extended_glob = oe;
+ extended_glob = extglob_flag;
}
if (arg1 != nullstr)
free (arg1);
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -125,7 +125,7 @@ do { \
} while (0)
#if defined (EXTENDED_GLOB)
-extern int extended_glob;
+extern int extended_glob, extglob_flag;
#endif
#if defined (TRANSLATABLE_STRINGS)
@@ -3304,7 +3304,7 @@ reset_parser ()
#if defined (EXTENDED_GLOB)
/* Reset to global value of extended glob */
if (parser_state & (PST_EXTPAT|PST_CMDSUBST))
- extended_glob = global_extglob;
+ extended_glob = extglob_flag;
#endif
if (parser_state & (PST_CMDSUBST|PST_STRING))
expand_aliases = expaliases_flag;
@@ -4124,10 +4124,10 @@ parse_comsub (qc, open, close, lenp, flags)
expand_aliases = posixly_correct != 0;
#if defined (EXTENDED_GLOB)
/* If (parser_state & PST_EXTPAT), we're parsing an extended pattern for a
- conditional command and have already set global_extglob appropriately. */
+ conditional command and have already set extended_glob appropriately. */
if (shell_compatibility_level <= 51 && was_extpat == 0)
{
- local_extglob = global_extglob = extended_glob;
+ local_extglob = extended_glob;
extended_glob = 1;
}
#endif
@@ -4235,7 +4235,7 @@ xparse_dolparen (base, string, indp, flags)
{
sh_parser_state_t ps;
sh_input_line_state_t ls;
- int orig_ind, nc, sflags, start_lineno;
+ int orig_ind, nc, sflags, start_lineno, local_extglob;
char *ret, *ep, *ostring;
/*debug_parser(1);*/
@@ -4278,7 +4278,7 @@ xparse_dolparen (base, string, indp, flags)
old value will be restored by restore_parser_state(). */
expand_aliases = 0;
#if defined (EXTENDED_GLOB)
- global_extglob = extended_glob; /* for reset_parser() */
+ local_extglob = extended_glob;
#endif
token_to_read = DOLPAREN; /* let's trick the parser */
@@ -4296,6 +4296,9 @@ xparse_dolparen (base, string, indp, flags)
restore_input_line_state (&ls);
restore_parser_state (&ps);
+#if defined (EXTENDED_GLOB)
+ extended_glob = local_extglob;
+#endif
token_to_read = 0;
/* If parse_string returns < 0, we need to jump to top level with the
@@ -4731,12 +4734,16 @@ cond_term ()
}
/* rhs */
+#if defined (EXTENDED_GLOB)
local_extglob = extended_glob;
if (parser_state & PST_EXTPAT)
extended_glob = 1;
+#endif
tok = read_token (READ);
+#if defined (EXTENDED_GLOB)
if (parser_state & PST_EXTPAT)
extended_glob = local_extglob;
+#endif
parser_state &= ~(PST_REGEXP|PST_EXTPAT);
if (tok == WORD)
@@ -4783,7 +4790,6 @@ parse_cond_command ()
{
COND_COM *cexp;
- global_extglob = extended_glob;
cexp = cond_expr ();
return (make_cond_command (cexp));
}
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 11
+#define PATCHLEVEL 12
#endif /* _PATCHLEVEL_H_ */
diff --git a/y.tab.c b/y.tab.c
--- a/y.tab.c
+++ b/y.tab.c
@@ -175,7 +175,7 @@ do { \
} while (0)
#if defined (EXTENDED_GLOB)
-extern int extended_glob;
+extern int extended_glob, extglob_flag;
#endif
#if defined (TRANSLATABLE_STRINGS)
@@ -5615,7 +5615,7 @@ reset_parser ()
#if defined (EXTENDED_GLOB)
/* Reset to global value of extended glob */
if (parser_state & (PST_EXTPAT|PST_CMDSUBST))
- extended_glob = global_extglob;
+ extended_glob = extglob_flag;
#endif
if (parser_state & (PST_CMDSUBST|PST_STRING))
expand_aliases = expaliases_flag;
@@ -6435,10 +6435,10 @@ parse_comsub (qc, open, close, lenp, flags)
expand_aliases = posixly_correct != 0;
#if defined (EXTENDED_GLOB)
/* If (parser_state & PST_EXTPAT), we're parsing an extended pattern for a
- conditional command and have already set global_extglob appropriately. */
+ conditional command and have already set extended_glob appropriately. */
if (shell_compatibility_level <= 51 && was_extpat == 0)
{
- local_extglob = global_extglob = extended_glob;
+ local_extglob = extended_glob;
extended_glob = 1;
}
#endif
@@ -6546,7 +6546,7 @@ xparse_dolparen (base, string, indp, flags)
{
sh_parser_state_t ps;
sh_input_line_state_t ls;
- int orig_ind, nc, sflags, start_lineno;
+ int orig_ind, nc, sflags, start_lineno, local_extglob;
char *ret, *ep, *ostring;
/*debug_parser(1);*/
@@ -6589,7 +6589,7 @@ xparse_dolparen (base, string, indp, flags)
old value will be restored by restore_parser_state(). */
expand_aliases = 0;
#if defined (EXTENDED_GLOB)
- global_extglob = extended_glob; /* for reset_parser() */
+ local_extglob = extended_glob;
#endif
token_to_read = DOLPAREN; /* let's trick the parser */
@@ -6607,6 +6607,9 @@ xparse_dolparen (base, string, indp, flags)
restore_input_line_state (&ls);
restore_parser_state (&ps);
+#if defined (EXTENDED_GLOB)
+ extended_glob = local_extglob;
+#endif
token_to_read = 0;
/* If parse_string returns < 0, we need to jump to top level with the
@@ -7042,12 +7045,16 @@ cond_term ()
}
/* rhs */
+#if defined (EXTENDED_GLOB)
local_extglob = extended_glob;
if (parser_state & PST_EXTPAT)
extended_glob = 1;
+#endif
tok = read_token (READ);
+#if defined (EXTENDED_GLOB)
if (parser_state & PST_EXTPAT)
extended_glob = local_extglob;
+#endif
parser_state &= ~(PST_REGEXP|PST_EXTPAT);
if (tok == WORD)
@@ -7094,7 +7101,6 @@ parse_cond_command ()
{
COND_COM *cexp;
- global_extglob = extended_glob;
cexp = cond_expr ();
return (make_cond_command (cexp));
}

@ -0,0 +1,34 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 12
+#define PATCHLEVEL 13
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -7497,8 +7497,6 @@ expand_arrayref:
? quote_string (temp)
: quote_escapes (temp);
rflags |= W_ARRAYIND;
- if (estatep)
- *estatep = es; /* structure copy */
}
/* Note that array[*] and array[@] expanded to a quoted null string by
returning the W_HASQUOTEDNULL flag to the caller in addition to TEMP. */
@@ -7507,7 +7505,9 @@ expand_arrayref:
else if (es.subtype == 2 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
rflags |= W_HASQUOTEDNULL;
- if (estatep == 0)
+ if (estatep)
+ *estatep = es; /* structure copy */
+ else
flush_eltstate (&es);
}
#endif

@ -0,0 +1,93 @@
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -3624,6 +3624,7 @@ execute_case_command (case_command)
free (pattern);
dispose_words (es);
+ QUIT;
if (match)
{
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 13
+#define PATCHLEVEL 14
#endif /* _PATCHLEVEL_H_ */
diff --git a/sig.c b/sig.c
--- a/sig.c
+++ b/sig.c
@@ -94,6 +94,7 @@ static SigHandler *old_winch = (SigHandler *)SIG_DFL;
#endif
static void initialize_shell_signals PARAMS((void));
+static void kill_shell PARAMS((int));
void
initialize_signals (reinit)
@@ -486,6 +487,8 @@ restore_sigmask ()
#endif
}
+static int handling_termsig = 0;
+
sighandler
termsig_sighandler (sig)
int sig;
@@ -532,6 +535,14 @@ termsig_sighandler (sig)
sig == terminating_signal)
terminate_immediately = 1;
+ /* If we are currently handling a terminating signal, we have a couple of
+ choices here. We can ignore this second terminating signal and let the
+ shell exit from the first one, or we can exit immediately by killing
+ the shell with this signal. This code implements the latter; to implement
+ the former, replace the kill_shell(sig) with return. */
+ if (handling_termsig)
+ kill_shell (sig); /* just short-circuit now */
+
terminating_signal = sig;
if (terminate_immediately)
@@ -564,16 +575,13 @@ void
termsig_handler (sig)
int sig;
{
- static int handling_termsig = 0;
- int i, core;
- sigset_t mask;
-
/* Simple semaphore to keep this function from being executed multiple
times. Since we no longer are running as a signal handler, we don't
block multiple occurrences of the terminating signals while running. */
if (handling_termsig)
return;
- handling_termsig = 1;
+
+ handling_termsig = terminating_signal; /* for termsig_sighandler */
terminating_signal = 0; /* keep macro from re-testing true. */
/* I don't believe this condition ever tests true. */
@@ -613,6 +621,16 @@ termsig_handler (sig)
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
+ kill_shell (sig);
+}
+
+static void
+kill_shell (sig)
+ int sig;
+{
+ int i, core;
+ sigset_t mask;
+
/* We don't change the set of blocked signals. If a user starts the shell
with a terminating signal blocked, we won't get here (and if by some
magic chance we do, we'll exit below). What we do is to restore the

@ -0,0 +1,163 @@
diff --git a/builtins/common.h b/builtins/common.h
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -51,6 +51,7 @@ do { \
#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */
#define SEVAL_ONECMD 0x100 /* only allow a single command */
#define SEVAL_NOHISTEXP 0x200 /* inhibit history expansion */
+#define SEVAL_NOOPTIMIZE 0x400 /* don't try to set optimization flags */
/* Flags for describe_command, shared between type.def and command.def */
#define CDESC_ALL 0x001 /* type -a */
diff --git a/builtins/eval.def b/builtins/eval.def
--- a/builtins/eval.def
+++ b/builtins/eval.def
@@ -53,5 +53,5 @@ eval_builtin (list)
return (EX_USAGE);
list = loptend; /* skip over possible `--' */
- return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS);
+ return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST|SEVAL_NOOPTIMIZE) : EXECUTION_SUCCESS);
}
diff --git a/builtins/evalstring.c b/builtins/evalstring.c
--- a/builtins/evalstring.c
+++ b/builtins/evalstring.c
@@ -132,8 +132,8 @@ optimize_connection_fork (command)
if (command->type == cm_connection &&
(command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
(command->value.Connection->second->flags & CMD_TRY_OPTIMIZING) &&
- ((startup_state == 2 && should_suppress_fork (command->value.Connection->second)) ||
- ((subshell_environment & SUBSHELL_PAREN) && should_optimize_fork (command->value.Connection->second, 0))))
+ (should_suppress_fork (command->value.Connection->second) ||
+ ((subshell_environment & SUBSHELL_PAREN) && should_optimize_fork (command->value.Connection->second, 0))))
{
command->value.Connection->second->flags |= CMD_NO_FORK;
command->value.Connection->second->value.Simple->flags |= CMD_NO_FORK;
@@ -290,6 +290,7 @@ parse_prologue (string, flags, tag)
(flags & SEVAL_NOFREE) -> don't free STRING when finished
(flags & SEVAL_RESETLINE) -> reset line_number to 1
(flags & SEVAL_NOHISTEXP) -> history_expansion_inhibited -> 1
+ (flags & SEVAL_NOOPTIMIZE) -> don't try to turn on optimizing flags
*/
int
@@ -502,7 +503,9 @@ parse_and_execute (string, from_file, flags)
if we are at the end of the command string, the last in a
series of connection commands is
command->value.Connection->second. */
- else if (command->type == cm_connection && can_optimize_connection (command))
+ else if (command->type == cm_connection &&
+ (flags & SEVAL_NOOPTIMIZE) == 0 &&
+ can_optimize_connection (command))
{
command->value.Connection->second->flags |= CMD_TRY_OPTIMIZING;
command->value.Connection->second->value.Simple->flags |= CMD_TRY_OPTIMIZING;
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1654,7 +1654,8 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
subshell sets an exit trap, so we set CMD_NO_FORK for simple commands
and set CMD_TRY_OPTIMIZING for simple commands on the right side of an
and-or or `;' list to test for optimizing forks when they are executed. */
- if (user_subshell && command->type == cm_subshell)
+ if (user_subshell && command->type == cm_subshell &&
+ (command->flags & (CMD_TIME_PIPELINE|CMD_INVERT_RETURN)) == 0)
optimize_subshell_command (command->value.Subshell->command);
/* Do redirections, then dispose of them before recursive call. */
diff --git a/jobs.c b/jobs.c
--- a/jobs.c
+++ b/jobs.c
@@ -4220,7 +4220,7 @@ run_sigchld_trap (nchild)
jobs_list_frozen = 1;
for (i = 0; i < nchild; i++)
{
- parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
+ parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE);
}
run_unwind_frame ("SIGCHLD trap");
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -2827,7 +2827,7 @@ execute_variable_command (command, vname)
if (last_lastarg)
last_lastarg = savestring (last_lastarg);
- parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST);
+ parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE);
restore_parser_state (&ps);
bind_variable ("_", last_lastarg, 0);
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 14
+#define PATCHLEVEL 15
#endif /* _PATCHLEVEL_H_ */
diff --git a/trap.c b/trap.c
--- a/trap.c
+++ b/trap.c
@@ -304,6 +304,7 @@ run_pending_traps ()
sh_parser_state_t pstate;
volatile int save_return_catch_flag, function_code;
procenv_t save_return_catch;
+ char *trap_command, *old_trap;
#if defined (ARRAY_VARS)
ARRAY *ps;
#endif
@@ -419,6 +420,9 @@ run_pending_traps ()
}
else
{
+ old_trap = trap_list[sig];
+ trap_command = savestring (old_trap);
+
save_parser_state (&pstate);
save_subst_varlist = subst_assign_varlist;
subst_assign_varlist = 0;
@@ -441,7 +445,8 @@ run_pending_traps ()
}
if (function_code == 0)
- x = parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
+ /* XXX is x always last_command_exit_value? */
+ x = parse_and_execute (trap_command, "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE);
else
{
parse_and_execute_cleanup (sig + 1); /* XXX - could use -1 */
@@ -1002,7 +1007,7 @@ run_exit_trap ()
if (code == 0 && function_code == 0)
{
reset_parser ();
- parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
+ parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE);
}
else if (code == ERREXIT)
retval = last_command_exit_value;
@@ -1109,7 +1114,7 @@ _run_trap_internal (sig, tag)
function_code = setjmp_nosigs (return_catch);
}
- flags = SEVAL_NONINT|SEVAL_NOHIST;
+ flags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE;
if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
flags |= SEVAL_RESETLINE;
evalnest++;
diff --git a/y.tab.c b/y.tab.c
--- a/y.tab.c
+++ b/y.tab.c
@@ -5138,7 +5138,7 @@ execute_variable_command (command, vname)
if (last_lastarg)
last_lastarg = savestring (last_lastarg);
- parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST);
+ parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE);
restore_parser_state (&ps);
bind_variable ("_", last_lastarg, 0);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,23 @@
diff --git a/builtins/evalfile.c b/builtins/evalfile.c
--- a/builtins/evalfile.c
+++ b/builtins/evalfile.c
@@ -266,7 +266,7 @@ file_error_and_exit:
#endif
/* set the flags to be passed to parse_and_execute */
- pflags = SEVAL_RESETLINE;
+ pflags = SEVAL_RESETLINE|SEVAL_NOOPTIMIZE;
pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
if (flags & FEVAL_BUILTIN)
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 16
+#define PATCHLEVEL 17
#endif /* _PATCHLEVEL_H_ */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,38 @@
diff --git a/jobs.c b/jobs.c
--- a/jobs.c
+++ b/jobs.c
@@ -3077,9 +3077,13 @@ if (job == NO_JOB)
/* Don't modify terminal pgrp if we are running in background or a
subshell. Make sure subst.c:command_substitute uses the same
conditions to determine whether or not it should undo this and
- give the terminal to pipeline_pgrp. */
-
+ give the terminal to pipeline_pgrp. We don't give the terminal
+ back to shell_pgrp if an async job in the background exits because
+ we never gave it to that job in the first place. An async job in
+ the foreground is one we started in the background and foregrounded
+ with `fg', and gave it the terminal. */
if ((flags & JWAIT_NOTERM) == 0 && running_in_background == 0 &&
+ (job == NO_JOB || IS_ASYNC (job) == 0 || IS_FOREGROUND (job)) &&
(subshell_environment & (SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0)
give_terminal_to (shell_pgrp, 0);
}
@@ -3623,6 +3627,7 @@ start_job (job, foreground)
{
get_tty_state ();
save_stty = shell_tty_info;
+ jobs[job]->flags &= ~J_ASYNC; /* no longer async */
/* Give the terminal to this job. */
if (IS_JOBCONTROL (job))
give_terminal_to (jobs[job]->pgrp, 0);
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 18
+#define PATCHLEVEL 19
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,25 @@
diff --git a/lib/readline/nls.c b/lib/readline/nls.c
--- a/lib/readline/nls.c
+++ b/lib/readline/nls.c
@@ -141,6 +141,10 @@ _rl_init_locale (void)
if (lspec == 0)
lspec = "";
ret = setlocale (LC_CTYPE, lspec); /* ok, since it does not change locale */
+ if (ret == 0 || *ret == 0)
+ ret = setlocale (LC_CTYPE, (char *)NULL);
+ if (ret == 0 || *ret == 0)
+ ret = RL_DEFAULT_LOCALE;
#else
ret = (lspec == 0 || *lspec == 0) ? RL_DEFAULT_LOCALE : lspec;
#endif
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 1
+#define PATCHLEVEL 2
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,33 @@
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -3150,6 +3150,7 @@ time_command_acceptable ()
case TIME: /* time time pipeline */
case TIMEOPT: /* time -p time pipeline */
case TIMEIGN: /* time -p -- ... */
+ case DOLPAREN:
return 1;
default:
return 0;
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 19
+#define PATCHLEVEL 20
#endif /* _PATCHLEVEL_H_ */
diff --git a/y.tab.c b/y.tab.c
--- a/y.tab.c
+++ b/y.tab.c
@@ -5465,6 +5465,7 @@ time_command_acceptable ()
case TIME: /* time time pipeline */
case TIMEOPT: /* time -p time pipeline */
case TIMEIGN: /* time -p -- ... */
+ case DOLPAREN:
return 1;
default:
return 0;

@ -0,0 +1,32 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 20
+#define PATCHLEVEL 21
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -1693,7 +1693,7 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags)
t = extract_command_subst (string, &si, flags);
CHECK_STRING_OVERRUN (i, si, slen, c);
- tlen = si - i - 1;
+ tlen = si - i - 2;
RESIZE_MALLOCED_BUFFER (result, result_index, tlen + 4, result_size, 64);
result[result_index++] = c;
result[result_index++] = LPAREN;
@@ -1713,7 +1713,7 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags)
t = extract_process_subst (string, (string[i] == '<' ? "<(" : ">)"), &si, flags);
CHECK_STRING_OVERRUN (i, si, slen, c);
- tlen = si - i - 1;
+ tlen = si - i - 2;
RESIZE_MALLOCED_BUFFER (result, result_index, tlen + 4, result_size, 64);
result[result_index++] = c;
result[result_index++] = LPAREN;

@ -0,0 +1,29 @@
diff --git a/lib/readline/display.c b/lib/readline/display.c
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -2683,11 +2683,8 @@ rl_forced_update_display (void)
register char *temp;
if (visible_line)
- {
- temp = visible_line;
- while (*temp)
- *temp++ = '\0';
- }
+ memset (visible_line, 0, line_size);
+
rl_on_new_line ();
forced_display++;
(*rl_redisplay_function) ();
diff --git a/patchlevel.h b/patchlevel.h
index 1712b108..e5e8cabd 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 21
+#define PATCHLEVEL 22
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,38 @@
diff --git a/builtins/declare.def b/builtins/declare.def
--- a/builtins/declare.def
+++ b/builtins/declare.def
@@ -420,11 +420,19 @@ declare_internal (list, local_var)
if (local_var && variable_context && STREQ (name, "-"))
{
+ int o;
+
+ o = localvar_inherit;
+ localvar_inherit = 0;
var = make_local_variable ("-", 0);
- FREE (value_cell (var)); /* just in case */
- value = get_current_options ();
- var_setvalue (var, value);
- VSETATTR (var, att_invisible);
+ localvar_inherit = o;
+
+ if (value_cell (var) == NULL) /* no duplicate instances */
+ {
+ value = get_current_options ();
+ var_setvalue (var, value);
+ VSETATTR (var, att_invisible);
+ }
NEXT_VARIABLE ();
}
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 22
+#define PATCHLEVEL 23
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,56 @@
diff --git a/arrayfunc.c b/arrayfunc.c
--- a/arrayfunc.c
+++ b/arrayfunc.c
@@ -650,7 +650,7 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
continue;
}
- aval = expand_subscript_string (v, 0);
+ aval = expand_assignment_string_to_string (v, 0);
if (aval == 0)
{
aval = (char *)xmalloc (1);
@@ -842,7 +842,7 @@ assign_compound_array_list (var, nlist, flags)
/* See above; we need to expand the value here */
if (assoc_p (var))
{
- val = expand_subscript_string (val, 0);
+ val = expand_assignment_string_to_string (val, 0);
if (val == 0)
{
val = (char *)xmalloc (1);
@@ -1030,7 +1030,7 @@ expand_and_quote_assoc_word (w, type)
nword[i++] = w[ind++];
nword[i++] = w[ind++];
- t = expand_subscript_string (w+ind, 0);
+ t = expand_assignment_string_to_string (w+ind, 0);
s = (t && strchr (t, CTLESC)) ? quote_escapes (t) : t;
value = sh_single_quote (s ? s : "");
if (s != t)
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 23
+#define PATCHLEVEL 24
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -10802,7 +10802,11 @@ expand_subscript_string (string, quoted)
oe = expand_no_split_dollar_star;
ret = (char *)NULL;
+#if 0
td.flags = W_NOPROCSUB|W_NOTILDE|W_NOSPLIT2; /* XXX - W_NOCOMSUB? */
+#else
+ td.flags = W_NOPROCSUB|W_NOSPLIT2; /* XXX - W_NOCOMSUB? */
+#endif
td.word = savestring (string); /* in case it's freed on error */
expand_no_split_dollar_star = 1;

@ -0,0 +1,24 @@
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1725,6 +1725,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE
: EXECUTION_SUCCESS;
+ /* Check for terminating signals before we return to our caller, which we
+ expect to exit immediately anyway. */
+ CHECK_TERMSIG;
/* If we were explicitly placed in a subshell with (), we need
to do the `shell cleanup' things, such as running traps[0]. */
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 24
+#define PATCHLEVEL 25
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,23 @@
diff --git a/lib/readline/colors.c b/lib/readline/colors.c
--- a/lib/readline/colors.c
+++ b/lib/readline/colors.c
@@ -73,7 +73,7 @@
static bool is_colored (enum indicator_no type);
static void restore_default_color (void);
-#define RL_COLOR_PREFIX_EXTENSION "readline-colored-completion-prefix"
+#define RL_COLOR_PREFIX_EXTENSION ".readline-colored-completion-prefix"
COLOR_EXT_TYPE *_rl_color_ext_list = 0;
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 25
+#define PATCHLEVEL 26
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,60 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 2
+#define PATCHLEVEL 3
#endif /* _PATCHLEVEL_H_ */
diff --git a/print_cmd.c b/print_cmd.c
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -297,10 +297,12 @@ make_command_string_internal (command)
case '\n': /* special case this */
{
char c = command->value.Connection->connector;
+ int was_newline;
s[0] = printing_comsub ? c : ';';
s[1] = '\0';
+ was_newline = deferred_heredocs == 0 && was_heredoc == 0 && c == '\n';
if (deferred_heredocs == 0)
{
if (was_heredoc == 0)
@@ -314,6 +316,8 @@ make_command_string_internal (command)
if (inside_function_def)
cprintf ("\n");
+ else if (printing_comsub && c == '\n' && was_newline == 0)
+ cprintf ("\n"); /* preserve newlines in comsubs but don't double them */
else
{
if (c == ';')
@@ -1365,7 +1369,11 @@ print_function_def (func)
cmdcopy->redirects = func_redirects;
}
else
- newline ("}");
+ {
+ /* { */
+ newline ("}");
+ was_heredoc = 0; /* not printing any here-documents now */
+ }
dispose_command (cmdcopy);
}
@@ -1442,7 +1450,10 @@ named_function_string (name, command, flags)
cmdcopy->redirects = func_redirects;
}
else
- newline ("}");
+ { /* { */
+ newline ("}");
+ was_heredoc = 0;
+ }
result = the_printed_command;

@ -0,0 +1,50 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 3
+#define PATCHLEVEL 4
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -1798,6 +1798,9 @@ extract_heredoc_dolbrace_string (string, sindex, quoted, flags)
return (result);
}
+#define PARAMEXPNEST_MAX 32 // for now
+static int dbstate[PARAMEXPNEST_MAX];
+
/* Extract a parameter expansion expression within ${ and } from STRING.
Obey the Posix.2 rules for finding the ending `}': count braces while
skipping over enclosed quoted strings and command substitutions.
@@ -1828,6 +1831,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
if (quoted == Q_HERE_DOCUMENT && dolbrace_state == DOLBRACE_QUOTE && (flags & SX_NOALLOC) == 0)
return (extract_heredoc_dolbrace_string (string, sindex, quoted, flags));
+ dbstate[0] = dolbrace_state;
+
pass_character = 0;
nesting_level = 1;
slen = strlen (string + *sindex) + *sindex;
@@ -1852,6 +1857,8 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
if (string[i] == '$' && string[i+1] == LBRACE)
{
+ if (nesting_level < PARAMEXPNEST_MAX)
+ dbstate[nesting_level] = dolbrace_state;
nesting_level++;
i += 2;
if (dolbrace_state == DOLBRACE_QUOTE || dolbrace_state == DOLBRACE_WORD)
@@ -1864,6 +1871,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
nesting_level--;
if (nesting_level == 0)
break;
+ dolbrace_state = (nesting_level < PARAMEXPNEST_MAX) ? dbstate[nesting_level] : dbstate[0]; /* Guess using initial state */
i++;
continue;
}

@ -0,0 +1,24 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 4
+#define PATCHLEVEL 5
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -8965,7 +8965,8 @@ pat_subst (string, pat, rep, mflags)
return (ret);
}
else if (*string == 0 && (match_pattern (string, pat, mtype, &s, &e) != 0))
- return ((mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2) : savestring (rep));
+ return (mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2)
+ : (rep ? savestring (rep) : savestring (""));
ret = (char *)xmalloc (rsize = 64);
ret[0] = '\0';

@ -0,0 +1,230 @@
diff --git a/builtins/common.h b/builtins/common.h
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -257,6 +257,8 @@ extern int print_shift_error;
extern int expand_once_flag;
#endif
+extern int expaliases_flag;
+
/* variables from source.def */
extern int source_searches_cwd;
extern int source_uses_path;
diff --git a/builtins/shopt.def b/builtins/shopt.def
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -149,6 +149,9 @@ static int shopt_set_complete_direxpand PARAMS((char *, int));
static int set_assoc_expand PARAMS((char *, int));
#endif
+int expaliases_flag = 0;
+static int shopt_set_expaliases PARAMS((char *, int));
+
static int shopt_set_debug_mode PARAMS((char *, int));
static int shopt_login_shell;
@@ -198,7 +201,7 @@ static struct {
#endif
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
{ "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
- { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
+ { "expand_aliases", &expaliases_flag, shopt_set_expaliases },
#if defined (DEBUGGER)
{ "extdebug", &debugging_mode, shopt_set_debug_mode },
#endif
@@ -350,7 +353,7 @@ reset_shopt_options ()
check_window_size = CHECKWINSIZE_DEFAULT;
allow_null_glob_expansion = glob_dot_filenames = 0;
no_exit_on_failed_exec = 0;
- expand_aliases = 0;
+ expand_aliases = expaliases_flag = 0;
extended_quote = 1;
fail_glob_expansion = 0;
glob_asciirange = GLOBASCII_DEFAULT;
@@ -631,6 +634,15 @@ shopt_set_debug_mode (option_name, mode)
return (0);
}
+static int
+shopt_set_expaliases (option_name, mode)
+ char *option_name;
+ int mode;
+{
+ expand_aliases = expaliases_flag;
+ return 0;
+}
+
#if defined (READLINE)
static int
shopt_enable_hostname_completion (option_name, mode)
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1536,7 +1536,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
expansion with `shopt -s expand_alias' to continue to expand
aliases. */
if (ois != interactive_shell)
- expand_aliases = 0;
+ expand_aliases = expaliases_flag = 0;
}
/* Subshells are neither login nor interactive. */
diff --git a/general.c b/general.c
--- a/general.c
+++ b/general.c
@@ -91,7 +91,7 @@ static struct {
{
&interactive_comments,
&source_uses_path,
- &expand_aliases,
+ &expaliases_flag,
&inherit_errexit,
&print_shift_error,
0
@@ -106,7 +106,8 @@ posix_initialize (on)
/* Things that should be turned on when posix mode is enabled. */
if (on != 0)
{
- interactive_comments = source_uses_path = expand_aliases = 1;
+ interactive_comments = source_uses_path = 1;
+ expand_aliases = expaliases_flag = 1;
inherit_errexit = 1;
source_searches_cwd = 0;
print_shift_error = 1;
@@ -116,13 +117,14 @@ posix_initialize (on)
else if (saved_posix_vars) /* on == 0, restore saved settings */
{
set_posix_options (saved_posix_vars);
+ expand_aliases = expaliases_flag;
free (saved_posix_vars);
saved_posix_vars = 0;
}
else /* on == 0, restore a default set of settings */
{
source_searches_cwd = 1;
- expand_aliases = interactive_shell;
+ expand_aliases = expaliases_flag = interactive_shell; /* XXX */
print_shift_error = 0;
}
}
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -3306,6 +3306,8 @@ reset_parser ()
if (parser_state & (PST_EXTPAT|PST_CMDSUBST))
extended_glob = global_extglob;
#endif
+ if (parser_state & (PST_CMDSUBST|PST_STRING))
+ expand_aliases = expaliases_flag;
parser_state = 0;
here_doc_first_line = 0;
@@ -4388,6 +4390,7 @@ parse_string_to_command (string, flags)
if (flags & SX_COMPLETE)
parser_state |= PST_NOERROR;
+ parser_state |= PST_STRING;
expand_aliases = 0;
cmd = 0;
@@ -6401,7 +6404,7 @@ parse_string_to_word_list (s, flags, whom)
/* State flags we don't want to persist into compound assignments. */
parser_state &= ~PST_NOEXPAND; /* parse_comsub sentinel */
/* State flags we want to set for this run through the tokenizer. */
- parser_state |= PST_COMPASSIGN|PST_REPARSE;
+ parser_state |= PST_COMPASSIGN|PST_REPARSE|PST_STRING;
}
while ((tok = read_token (READ)) != yacc_EOF)
diff --git a/parser.h b/parser.h
--- a/parser.h
+++ b/parser.h
@@ -50,6 +50,7 @@
#define PST_ENDALIAS 0x200000 /* just finished expanding and consuming an alias */
#define PST_NOEXPAND 0x400000 /* don't expand anything in read_token_word; for command substitution */
#define PST_NOERROR 0x800000 /* don't print error messages in yyerror */
+#define PST_STRING 0x1000000 /* parsing a string to a command or word list */
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
struct dstack {
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 5
+#define PATCHLEVEL 6
#endif /* _PATCHLEVEL_H_ */
diff --git a/shell.c b/shell.c
--- a/shell.c
+++ b/shell.c
@@ -1844,8 +1844,8 @@ reset_option_defaults ()
static void
init_interactive ()
{
- expand_aliases = interactive_shell = startup_state = 1;
- interactive = 1;
+ expand_aliases = expaliases_flag = 1;
+ interactive_shell = startup_state = interactive = 1;
#if defined (HISTORY)
if (enable_history_list == -1)
enable_history_list = 1; /* set default */
@@ -1865,7 +1865,7 @@ init_noninteractive ()
bash_history_reinit (0);
#endif /* HISTORY */
interactive_shell = startup_state = interactive = 0;
- expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
+ expand_aliases = expaliases_flag = posixly_correct; /* XXX - was 0 not posixly_correct */
no_line_editing = 1;
#if defined (JOB_CONTROL)
/* Even if the shell is not interactive, enable job control if the -i or
@@ -1882,7 +1882,7 @@ init_interactive_script ()
enable_history_list = 1;
#endif
init_noninteractive ();
- expand_aliases = interactive_shell = startup_state = 1;
+ expand_aliases = expaliases_flag = interactive_shell = startup_state = 1;
#if defined (HISTORY)
remember_on_history = enable_history_list; /* XXX */
#endif
@@ -2025,7 +2025,7 @@ shell_reinitialize ()
debugging = do_version = line_number = last_command_exit_value = 0;
forced_interactive = interactive_shell = 0;
subshell_environment = running_in_background = 0;
- expand_aliases = 0;
+ expand_aliases = expaliases_flag = 0;
bash_argv_initialized = 0;
/* XXX - should we set jobs_m_flag to 0 here? */
diff --git a/y.tab.c b/y.tab.c
--- a/y.tab.c
+++ b/y.tab.c
@@ -5617,6 +5617,8 @@ reset_parser ()
if (parser_state & (PST_EXTPAT|PST_CMDSUBST))
extended_glob = global_extglob;
#endif
+ if (parser_state & (PST_CMDSUBST|PST_STRING))
+ expand_aliases = expaliases_flag;
parser_state = 0;
here_doc_first_line = 0;
@@ -6699,6 +6701,7 @@ parse_string_to_command (string, flags)
if (flags & SX_COMPLETE)
parser_state |= PST_NOERROR;
+ parser_state |= PST_STRING;
expand_aliases = 0;
cmd = 0;
@@ -8712,7 +8715,7 @@ parse_string_to_word_list (s, flags, whom)
/* State flags we don't want to persist into compound assignments. */
parser_state &= ~PST_NOEXPAND; /* parse_comsub sentinel */
/* State flags we want to set for this run through the tokenizer. */
- parser_state |= PST_COMPASSIGN|PST_REPARSE;
+ parser_state |= PST_COMPASSIGN|PST_REPARSE|PST_STRING;
}
while ((tok = read_token (READ)) != yacc_EOF)

@ -0,0 +1,206 @@
diff --git a/builtins/evalstring.c b/builtins/evalstring.c
--- a/builtins/evalstring.c
+++ b/builtins/evalstring.c
@@ -431,6 +431,8 @@ parse_and_execute (string, from_file, flags)
if (parse_command () == 0)
{
+ int local_expalias, local_alflag;
+
if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute))
{
last_result = EXECUTION_SUCCESS;
@@ -507,6 +509,19 @@ parse_and_execute (string, from_file, flags)
}
#endif /* ONESHOT */
+ /* We play tricks in the parser and command_substitute() turning
+ expand_aliases on and off depending on which parsing pass and
+ whether or not we're in posix mode. This only matters for
+ parsing, and we let the higher layers deal with that. We just
+ want to ensure that expand_aliases is set to the appropriate
+ global value when we go to execute this command, so we save
+ and restore it around the execution (we don't restore it if
+ the global value of the flag (expaliases_flag) changes). */
+ local_expalias = expand_aliases;
+ local_alflag = expaliases_flag;
+ if (subshell_environment & SUBSHELL_COMSUB)
+ expand_aliases = expaliases_flag;
+
/* See if this is a candidate for $( <file ). */
if (startup_state == 2 &&
(subshell_environment & SUBSHELL_COMSUB) &&
@@ -524,6 +539,10 @@ parse_and_execute (string, from_file, flags)
dispose_fd_bitmap (bitmap);
discard_unwind_frame ("pe_dispose");
+ /* If the global value didn't change, we restore what we had. */
+ if ((subshell_environment & SUBSHELL_COMSUB) && local_alflag == expaliases_flag)
+ expand_aliases = local_expalias;
+
if (flags & SEVAL_ONECMD)
{
reset_parser ();
diff --git a/command.h b/command.h
--- a/command.h
+++ b/command.h
@@ -114,6 +114,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
#define PF_COMPLETE 0x10 /* same as W_COMPLETE, sets SX_COMPLETE */
#define PF_EXPANDRHS 0x20 /* same as W_EXPANDRHS */
#define PF_ALLINDS 0x40 /* array, act as if [@] was supplied */
+#define PF_BACKQUOTE 0x80 /* differentiate `` from $() for command_substitute */
/* Possible values for subshell_environment */
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
diff --git a/parse.y b/parse.y
--- a/parse.y
+++ b/parse.y
@@ -3612,6 +3612,7 @@ tokword:
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
+#define P_ARITH 0x0080 /* parsing a $(( )) arithmetic expansion */
/* Lexical state while parsing a grouping construct or $(...). */
#define LEX_WASDOL 0x0001
@@ -3910,6 +3911,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
}
else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
goto parse_dollar_word;
+ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/
+ /* $() inside $(( ))/$[ ] */
+ goto parse_dollar_word;
#if defined (PROCESS_SUBSTITUTION)
/* XXX - technically this should only be recognized at the start of
a word */
@@ -3940,7 +3944,7 @@ parse_dollar_word:
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
+ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags|P_ARITH);
CHECK_NESTRET_ERROR ();
APPEND_NESTRET ();
@@ -4079,7 +4083,7 @@ parse_comsub (qc, open, close, lenp, flags)
peekc = shell_getc (1);
shell_ungetc (peekc);
if (peekc == '(') /*)*/
- return (parse_matched_pair (qc, open, close, lenp, 0));
+ return (parse_matched_pair (qc, open, close, lenp, P_ARITH));
}
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
@@ -4500,7 +4504,7 @@ parse_arith_cmd (ep, adddq)
int ttoklen;
exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
+ ttok = parse_matched_pair (0, '(', ')', &ttoklen, P_ARITH);
rval = 1;
if (ttok == &matched_pair_error)
return -1;
@@ -5015,7 +5019,7 @@ read_token_word (character)
pop_delimiter (dstack);
}
else
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
+ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARITH);
if (ttok == &matched_pair_error)
return -1; /* Bail immediately. */
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 6
+#define PATCHLEVEL 7
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -7123,8 +7123,12 @@ command_substitute (string, quoted, flags)
remove_quoted_escapes (string);
/* We want to expand aliases on this pass if we are not in posix mode
- for backwards compatibility. */
- if (expand_aliases)
+ for backwards compatibility. parse_and_execute() takes care of
+ setting expand_aliases back to the global value when executing the
+ parsed string. We only do this for $(...) command substitution,
+ since that is what parse_comsub handles; `` comsubs are processed
+ using parse.y:parse_matched_pair(). */
+ if (expand_aliases && (flags & PF_BACKQUOTE) == 0)
expand_aliases = posixly_correct == 0;
startup_state = 2; /* see if we can avoid a fork */
@@ -11292,7 +11296,7 @@ add_string:
else
{
de_backslash (temp);
- tword = command_substitute (temp, quoted, 0);
+ tword = command_substitute (temp, quoted, PF_BACKQUOTE);
temp1 = tword ? tword->word : (char *)NULL;
if (tword)
dispose_word_desc (tword);
diff --git a/y.tab.c b/y.tab.c
--- a/y.tab.c
+++ b/y.tab.c
@@ -5923,6 +5923,7 @@ tokword:
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
+#define P_ARITH 0x0080 /* parsing a $(( )) arithmetic expansion */
/* Lexical state while parsing a grouping construct or $(...). */
#define LEX_WASDOL 0x0001
@@ -6221,6 +6222,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
}
else if ((flags & (P_ARRAYSUB|P_DOLBRACE)) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
goto parse_dollar_word;
+ else if ((flags & P_ARITH) && (tflags & LEX_WASDOL) && ch == '(') /*)*/
+ /* $() inside $(( ))/$[ ] */
+ goto parse_dollar_word;
#if defined (PROCESS_SUBSTITUTION)
/* XXX - technically this should only be recognized at the start of
a word */
@@ -6251,7 +6255,7 @@ parse_dollar_word:
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
+ nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags|P_ARITH);
CHECK_NESTRET_ERROR ();
APPEND_NESTRET ();
@@ -6390,7 +6394,7 @@ parse_comsub (qc, open, close, lenp, flags)
peekc = shell_getc (1);
shell_ungetc (peekc);
if (peekc == '(') /*)*/
- return (parse_matched_pair (qc, open, close, lenp, 0));
+ return (parse_matched_pair (qc, open, close, lenp, P_ARITH));
}
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
@@ -6811,7 +6815,7 @@ parse_arith_cmd (ep, adddq)
int ttoklen;
exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
+ ttok = parse_matched_pair (0, '(', ')', &ttoklen, P_ARITH);
rval = 1;
if (ttok == &matched_pair_error)
return -1;
@@ -7326,7 +7330,7 @@ read_token_word (character)
pop_delimiter (dstack);
}
else
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
+ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARITH);
if (ttok == &matched_pair_error)
return -1; /* Bail immediately. */
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 3,

@ -0,0 +1,34 @@
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 7
+#define PATCHLEVEL 8
#endif /* _PATCHLEVEL_H_ */
diff --git a/subst.c b/subst.c
--- a/subst.c
+++ b/subst.c
@@ -3819,6 +3819,10 @@ pos_params (string, start, end, quoted, pflags)
#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
#endif
+/* We don't perform process substitution in arithmetic expressions, so don't
+ bother checking for it. */
+#define ARITH_EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
+
/* If there are any characters in STRING that require full expansion,
then call FUNC to expand STRING; otherwise just perform quote
removal if necessary. This returns a new string. */
@@ -4028,7 +4032,7 @@ expand_arith_string (string, quoted)
i = saw_quote = 0;
while (string[i])
{
- if (EXP_CHAR (string[i]))
+ if (ARITH_EXP_CHAR (string[i]))
break;
else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
saw_quote = string[i];

@ -0,0 +1,23 @@
diff --git a/expr.c b/expr.c
--- a/expr.c
+++ b/expr.c
@@ -1168,6 +1168,8 @@ expr_streval (tok, e, lvalue)
/* [[[[[ */
#if defined (ARRAY_VARS)
aflag = tflag; /* use a different variable for now */
+ if (shell_compatibility_level > 51)
+ aflag |= AV_ATSTARKEYS;
v = (e == ']') ? array_variable_part (tok, tflag, (char **)0, (int *)0) : find_variable (tok);
#else
v = find_variable (tok);
diff --git a/patchlevel.h b/patchlevel.h
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 8
+#define PATCHLEVEL 9
#endif /* _PATCHLEVEL_H_ */

@ -0,0 +1,20 @@
Another C compatibility issue: char ** and char * are distinct types,
and strtold expects the former for its second argument.
Submitted upstream:
<https://lists.gnu.org/archive/html/bug-bash/2023-11/msg00104.html>
diff --git a/configure.ac b/configure.ac
index 6defea0835fe8877..955c1149a8141e19 100644
--- a/configure.ac
+++ b/configure.ac
@@ -885,7 +885,7 @@ AC_CHECK_DECLS([strtold], [
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdlib.h>]],
- [[long double r; char *foo, bar; r = strtold(foo, &bar);]]
+ [[long double r; char *foo, *bar; r = strtold(foo, &bar);]]
)],
[bash_cv_strtold_broken=no],[bash_cv_strtold_broken=yes])
]

@ -0,0 +1,21 @@
Avoid an implicit declaration of dup2 in its configure probe. This
prevents build issues with future compilers.
Already reported upstream:
<https://lists.gnu.org/archive/html/bug-bash/2023-02/msg00000.html>
diff --git a/aclocal.m4 b/aclocal.m4
index 6162f6eb9ef90754..5cbbe96d7158197a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -238,6 +238,9 @@ AC_CACHE_VAL(bash_cv_dup2_broken,
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
int
main()
{

@ -0,0 +1,307 @@
diff --git a/builtins.h b/builtins.h
--- a/builtins.h
+++ b/builtins.h
@@ -46,6 +46,7 @@
#define POSIX_BUILTIN 0x20 /* This builtins is special in the Posix command search order. */
#define LOCALVAR_BUILTIN 0x40 /* This builtin creates local variables */
#define ARRAYREF_BUILTIN 0x80 /* This builtin takes array references as arguments */
+#define REQUIRES_BUILTIN 0x100 /* This builtin requires other files. */
#define BASE_INDENT 4
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -69,11 +69,16 @@ extern char *strcpy ();
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
/* Flag values that builtins can have. */
+/* These flags are for the C code generator,
+ the C which is produced (./builtin.c)
+ includes the flags definitions found
+ in ../builtins.h */
#define BUILTIN_FLAG_SPECIAL 0x01
#define BUILTIN_FLAG_ASSIGNMENT 0x02
#define BUILTIN_FLAG_LOCALVAR 0x04
#define BUILTIN_FLAG_POSIX_BUILTIN 0x08
#define BUILTIN_FLAG_ARRAYREF_ARG 0x10
+#define BUILTIN_FLAG_REQUIRES 0x20
#define BASE_INDENT 4
@@ -189,13 +194,21 @@ char *arrayvar_builtins[] =
"typeset", "unset", "wait", /*]*/
(char *)NULL
};
-
+
+/* The builtin commands that cause requirements on other files. */
+static char *requires_builtins[] =
+{
+ ".", "command", "exec", "source", "inlib",
+ (char *)NULL
+};
+
/* 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_arrayvar_builtin ();
+static int is_requires_builtin ();
#if !defined (HAVE_RENAME)
static int rename ();
@@ -856,6 +869,8 @@ builtin_handler (self, defs, arg)
new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
if (is_arrayvar_builtin (name))
new->flags |= BUILTIN_FLAG_ARRAYREF_ARG;
+ if (is_requires_builtin (name))
+ new->flags |= BUILTIN_FLAG_REQUIRES;
array_add ((char *)new, defs->builtins);
building_builtin = 1;
@@ -1275,13 +1290,14 @@ write_builtins (defs, structfile, externfile)
else
fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
- fprintf (structfile, "%s%s%s%s%s%s, %s_doc,\n",
+ fprintf (structfile, "%s%s%s%s%s%s%s, %s_doc,\n",
"BUILTIN_ENABLED | STATIC_BUILTIN",
(builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
(builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
(builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "",
(builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
(builtin->flags & BUILTIN_FLAG_ARRAYREF_ARG) ? " | ARRAYREF_BUILTIN" : "",
+ (builtin->flags & BUILTIN_FLAG_REQUIRES) ? " | REQUIRES_BUILTIN" : "",
document_name (builtin));
/* Don't translate short document summaries that are identical
@@ -1678,6 +1694,13 @@ is_arrayvar_builtin (name)
return (_find_in_table (name, arrayvar_builtins));
}
+static int
+is_requires_builtin (name)
+ char *name;
+{
+ return (_find_in_table (name, requires_builtins));
+}
+
#if !defined (HAVE_RENAME)
static int
rename (from, to)
diff --git a/doc/bash.1 b/doc/bash.1
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -239,6 +239,14 @@ The shell becomes restricted (see
.B "RESTRICTED SHELL"
below).
.TP
+.B \-\-rpm-requires
+Produce the list of files that are required for the
+shell script to run. This implies '-n' and is subject
+to the same limitations as compile time error checking checking;
+Command substitutions, Conditional expressions and
+.BR eval
+builtin are not parsed so some dependencies may be missed.
+.TP
.B \-\-verbose
Equivalent to \fB\-v\fP.
.TP
diff --git a/doc/bashref.texi b/doc/bashref.texi
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -6927,6 +6927,13 @@ standard. @xref{Bash POSIX Mode}, for a description of the Bash
@item --restricted
Make the shell a restricted shell (@pxref{The Restricted Shell}).
+@item --rpm-requires
+Produce the list of files that are required for the
+shell script to run. This implies '-n' and is subject
+to the same limitations as compile time error checking checking;
+Command substitutions, Conditional expressions and @command{eval}
+are not parsed so some dependencies may be missed.
+
@item --verbose
Equivalent to @option{-v}. Print shell input lines as they're read.
diff --git a/eval.c b/eval.c
--- a/eval.c
+++ b/eval.c
@@ -138,7 +138,8 @@ reader_loop ()
if (read_command () == 0)
{
- if (interactive_shell == 0 && read_but_dont_execute)
+
+ if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires))
{
set_exit_status (last_command_exit_value);
dispose_command (global_command);
diff --git a/execute_cmd.c b/execute_cmd.c
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -561,6 +561,8 @@ async_redirect_stdin ()
#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
+extern int rpm_requires;
+
/* Execute the command passed in COMMAND, perhaps doing it asynchronously.
COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
ASYNCHRONOUS, if non-zero, says to do this command in the background.
@@ -592,7 +594,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (breaking || continuing)
return (last_command_exit_value);
- if (read_but_dont_execute)
+ if (command == 0 || (read_but_dont_execute && !rpm_requires))
+ return (EXECUTION_SUCCESS);
+ if (rpm_requires && command->type == cm_function_def)
+ return last_command_exit_value =
+ execute_intern_function (command->value.Function_def->name,
+ command->value.Function_def);
+ if (read_but_dont_execute)
return (last_command_exit_value);
if (command == 0)
return (EXECUTION_SUCCESS);
@@ -2883,7 +2891,7 @@ execute_for_command (for_command)
save_line_number = line_number;
if (check_identifier (for_command->name, 1) == 0)
{
- if (posixly_correct && interactive_shell == 0)
+ if (posixly_correct && interactive_shell == 0 && rpm_requires == 0)
{
last_command_exit_value = EX_BADUSAGE;
jump_to_top_level (ERREXIT);
diff --git a/execute_cmd.h b/execute_cmd.h
--- a/execute_cmd.h
+++ b/execute_cmd.h
@@ -22,6 +22,9 @@
#define _EXECUTE_CMD_H_
#include "stdc.h"
+#include "variables.h"
+#include "command.h"
+
#if defined (ARRAY_VARS)
struct func_array_state
diff --git a/make_cmd.c b/make_cmd.c
--- a/make_cmd.c
+++ b/make_cmd.c
@@ -35,6 +35,8 @@
#include "bashintl.h"
#include "shell.h"
+#include "builtins.h"
+#include "builtins/common.h"
#include "execute_cmd.h"
#include "parser.h"
#include "flags.h"
@@ -839,6 +841,30 @@ make_coproc_command (name, command)
return (make_command (cm_coproc, (SIMPLE_COM *)temp));
}
+static void
+output_requirement (deptype, filename)
+const char *deptype;
+char *filename;
+{
+ static char *alphabet_set = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ if (strchr(filename, '$') || (filename[0] != '/' && strchr(filename, '/')))
+ return;
+
+ /*
+ if the executable is called via variable substitution we can
+ not dermine what it is at compile time.
+
+ if the executable consists only of characters not in the
+ alphabet we do not consider it a dependency just an artifact
+ of shell parsing (ex "exec < ${infile}").
+ */
+
+ if (strpbrk(filename, alphabet_set))
+ printf ("%s(%s)\n", deptype, filename);
+}
+
/* Reverse the word list and redirection list in the simple command
has just been parsed. It seems simpler to do this here the one
time then by any other method that I can think of. */
@@ -856,6 +882,28 @@ clean_simple_command (command)
REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
}
+ if (rpm_requires && command->value.Simple->words)
+ {
+ char *cmd0;
+ char *cmd1;
+ struct builtin *b;
+
+ cmd0 = command->value.Simple->words->word->word;
+ b = builtin_address_internal (cmd0, 0);
+ cmd1 = 0;
+ if (command->value.Simple->words->next)
+ cmd1 = command->value.Simple->words->next->word->word;
+
+ if (b) {
+ if ( (b->flags & REQUIRES_BUILTIN) && cmd1)
+ output_requirement ("executable", cmd1);
+ } else {
+ if (!assignment(cmd0, 0))
+ output_requirement (find_function(cmd0) ? "function" : "executable", cmd0);
+ }
+ } /*rpm_requires*/
+
+
parser_state &= ~PST_REDIRLIST;
return (command);
}
diff --git a/shell.c b/shell.c
--- a/shell.c
+++ b/shell.c
@@ -196,6 +196,9 @@ int have_devfd = 0;
/* The name of the .(shell)rc file. */
static char *bashrc_file = DEFAULT_BASHRC;
+/* Non-zero if we are finding the scripts requirements. */
+int rpm_requires;
+
/* Non-zero means to act more like the Bourne shell on startup. */
static int act_like_sh;
@@ -266,6 +269,7 @@ static const struct {
{ "protected", Int, &protected_mode, (char **)0x0 },
#endif
{ "rcfile", Charp, (int *)0x0, &bashrc_file },
+ { "rpm-requires", Int, &rpm_requires, (char **)0x0 },
#if defined (RESTRICTED_SHELL)
{ "restricted", Int, &restricted, (char **)0x0 },
#endif
@@ -510,6 +514,12 @@ main (argc, argv, env)
read_but_dont_execute = 1;
#endif
+ if (rpm_requires)
+ {
+ read_but_dont_execute = 1;
+ initialize_shell_builtins ();
+ }
+
if (running_setuid && privileged_mode == 0)
disable_priv_mode ();
diff --git a/shell.h b/shell.h
--- a/shell.h
+++ b/shell.h
@@ -100,6 +100,7 @@ extern int interactive, interactive_shell;
extern int startup_state;
extern int reading_shell_script;
extern int shell_initialized;
+extern int rpm_requires;
extern int bash_argv_initialized;
extern int subshell_environment;
extern int current_command_number;

@ -0,0 +1,10 @@
--- bash-3.0/builtins/setattr.def.setlocale 2005-08-08 12:22:42.000000000 +0100
+++ bash-3.0/builtins/setattr.def 2005-08-08 12:25:16.000000000 +0100
@@ -423,4 +423,7 @@
if (var && (exported_p (var) || (attribute & att_exported)))
array_needs_making++; /* XXX */
+
+ if (var)
+ stupidly_hack_special_variables (name);
}

@ -0,0 +1,57 @@
diff --git a/tests/exec.right b/tests/exec.right
--- a/tests/exec.right
+++ b/tests/exec.right
@@ -60,7 +60,6 @@ this is ohio-state
0
1
testb
-expand_aliases on
1
1
1
diff --git a/tests/execscript b/tests/execscript
--- a/tests/execscript
+++ b/tests/execscript
@@ -108,8 +108,6 @@ ${THIS_SH} ./exec6.sub
# checks for properly deciding what constitutes an executable file
${THIS_SH} ./exec7.sub
-${THIS_SH} -i ${PWD}/exec8.sub
-
${THIS_SH} ./exec9.sub
${THIS_SH} ./exec10.sub
diff --git a/tests/read.right b/tests/read.right
--- a/tests/read.right
+++ b/tests/read.right
@@ -34,17 +34,6 @@ xyz
a = xyz
a = -xyz 123-
a = abc
-timeout 1: ok
-unset or null 1
-timeout 2: ok
-unset or null 2
-timeout 3: ok
-unset or null 3
-./read2.sub: line 45: read: -3: invalid timeout specification
-1
-
-abcde
-abcde
./read3.sub: line 17: read: -1: invalid number
abc
defg
diff --git a/tests/read.tests b/tests/read.tests
--- a/tests/read.tests
+++ b/tests/read.tests
@@ -95,9 +95,6 @@ echo " foo" | { IFS=$':' ; read line; recho "$line"; }
# test read -d delim behavior
${THIS_SH} ./read1.sub
-# test read -t timeout behavior
-${THIS_SH} ./read2.sub
-
# test read -n nchars behavior
${THIS_SH} ./read3.sub

@ -0,0 +1,24 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.4 (Darwin)
mQGiBEEOsGwRBACFa0A1oa71HSZLWxAx0svXzhOZNQZOzqHmSuGOG92jIpQpr8Dp
vgRh40YpAwdcXb8QG1J5yGAKeevNE1zCFaA725vGSdHUyypHouV0xoWwukYO6qly
yX+2BZU+okBUqoWQkoWxiYaCSfzB2Ln7pmdys1fJhcgBKf3VjWCjd2XJTwCgoFJO
wyBFJdugjfwjSoRSwDOIMf0D/iQKqlWhIO1LGpMrGX0il0/x4zj0NAcSwAk7LaPZ
bN4UPjn5pqGEHBlf1+xDDQCkAoZ/VqESGZragl4VqJfxBr29Ag0UDvNbUbXoxQsA
Rdero1M8GiAIRc50hj7HXFoERwenbNDJL86GPLAQOTGOCa4W2o29nFfFjQrsrrYH
zVtyA/9oyKvTeEMJ7NA3VJdWcmn7gOu0FxEmSNhSoV1T4vP21Wf7f5niCCRKQLNy
Uy0wEApQi4tSysdz+AbgAc0b/bHYVzIf2uO2lIEZQNNt+3g2bmXgloWmW5fsm/di
50Gm1l1Na63d3RZ00SeFQos6WEwLUHEB0yp6KXluXLLIZitEJLQaQ2hldCBSYW1l
eSA8Y2hldEBjd3J1LmVkdT6IXgQTEQIAHgUCQQ6wbAIbAwYLCQgHAwIDFQIDAxYC
AQIeAQIXgAAKCRC7WGnwZOp0q87NAJ99FEzFvDdYzqCczXF6KKXi7YN5OACfacDY
soZcnnsy7EjBZL0zwGwb/sG5AQ0EQQ6wbxAEAJCukwDigRDPhAuI+lf+6P64lWan
IFOXIndqhvU13cDbQ/Wt5LwPzm2QTvd7F+fcHOgZ8KOFScbDpjJaRqwIybMTcIN0
B2pBLX/C10W1aY+cUrXZgXUGVISEMmpaP9v02auToo7XXVEHC+XLO9IU7/xaU98F
L69l6/K4xeNSBRM/AAMHA/wNAmRBpcyK0+VggZ5esQaIP/LyolAm2qwcmrd3dZi+
g24s7yjV0EUwvRP7xHRDQFgkAo6++QbuecU/J90lxrVnQwucZmfz9zgWDkT/MpfB
/CNRSKLFjhYq2yHmHWT6vEjw9Ry/hF6Pc0oh1a62USdfaKAiim0nVxxQmPmiRvtC
mYhJBBgRAgAJBQJBDrBvAhsMAAoJELtYafBk6nSr43AAn2ZZFQg8Gs/zUzvXMt7e
vaFqVTzcAJ0cHtKpP1i/4H4R9+OsYeQdxxWxTQ==
=2MjR
-----END PGP PUBLIC KEY BLOCK-----

@ -0,0 +1,2 @@
# ~/.bash_logout

@ -0,0 +1,8 @@
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs

@ -0,0 +1,25 @@
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]; then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
if [ -d ~/.bashrc.d ]; then
for rc in ~/.bashrc.d/*; do
if [ -f "$rc" ]; then
. "$rc"
fi
done
fi
unset rc

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save