FIFOs reported by Zev Weiss <zev@bewilderbeest.net>
- execute_null_command: do the same thing in the parent branch after
make_child
+
+ 11/14
+ -----
+subst.c
+ - parameter_brace_expand: a variable is null if it's special ($@, $*),
+ the expansion occurs within double quotes, and the expansion turns
+ into a quoted null. Fixes debian bug 692447 reported by
+ Matrosov Dmitriy <sgf.dma@gmail.com>
+
+jobs.c
+ - run_sigchld_trap: make sure `running_trap' sentinel is set
+ appropriately
+ - waitchld: only run the sigchld trap if we're not in a signal
+ handler, not running a trap, and executing the wait builtin.
+ Otherwise, queue for later handling. We still run one instance
+ of the trap handler per exited child. Bulk of fix for bug
+ reported by Elliott Forney <idfah@cs.colostate.edu>
+
+trap.c
+ - queue_sigchld_trap: set catch_flag so run_pending_traps notices,
+ and set trapped_signal_received for completeness. Rest of fix
+ for bug reported by Elliott Forney <idfah@cs.colostate.edu>
+
+lib/malloc/malloc.c
+ - block_signals: renamed to _malloc_block_signals, made public
+ - unblock_signals: renamed to _malloc_unblock_signals, made public
+
+lib/malloc/imalloc.h
+ - extern declarations for _malloc_{un,}block_signals
+
+lib/malloc/table.c
+ - mregister_alloc, mregister_free: block signals around table
+ manipulation
+
+ 11/15
+ -----
+trap.c
+ - run_pending_traps: set SIG_INPROGRESS flag around calls to
+ run_sigchld_handler so other parts of the shell know that the
+ SIGCHLD trap handler is executing
+ - run_pending_traps: if we get a situation where we are looking at
+ running a SIGCHLD trap but the trap string is IMPOSSIBLE_TRAP_HANDLER
+ and the SIG_INPROGRESS flag is set, just skip it. This is possible
+ if run_pending_traps is called from a SIGCHLD trap handler run by
+ run_sigchld_trap
+
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+ - corrected description of the effect of `set history-size 0'. Report
+ from Vesa-Matti J Kari <vmkari@cc.helsinki.fi>
+
+include/stdc.h
+ - CPP_STRING: new define, replaces __STRING
+
+lib/malloc/{malloc.c,imalloc.h}
+ - replace __STRING with CPP_STRING
+
+ 11/16
+ -----
+lib/readline/bind.c
+ - sv_histsize: if argument evaluates to a value < 0, unstifle the
+ history
tests/dollar-star3.sub f
tests/dollar-star4.sub f
tests/dollar-star5.sub f
+tests/dollar-star6.sub f
tests/dollar.right f
tests/dstack.tests f
tests/dstack.right f
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
-.\" Last Change: Sun Oct 7 17:59:28 EDT 2012
+.\" Last Change: Thu Nov 15 21:03:47 EST 2012
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2012 October 7" "GNU Bash 4.2"
+.TH BASH 1 "2012 November 15" "GNU Bash 4.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
or \fBnext-history\fP.
.TP
.B history\-size (0)
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
+Set the maximum number of history entries saved in the history list.
+If set to zero, any existing history entries are deleted and no new entries
+are saved.
+If set to a value less than zero, the number of history entries is not
+limited.
+By default, the number of history entries is not limited.
.TP
.B horizontal\-scroll\-mode (Off)
When set to \fBOn\fP, makes readline use a single line for display,
# endif
#endif
+/* Fortify, at least, has trouble with this definition */
#if defined (HAVE_STRINGIZE)
-# define __STRING(x) #x
+# define CPP_STRING(x) #x
#else
-# define __STRING(x) "x"
+# define CPP_STRING(x) "x"
#endif
#if !defined (__STDC__)
}
#if defined (DEBUG)
+# if 0
itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);
itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);
itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, j);
itrace ("realloc_jobs_list: js.j_ndead %d js.c_reaped %d", js.j_ndead, js.c_reaped);
+# endif
#endif
js.j_firstj = 0;
reset_current ();
#ifdef DEBUG
- itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);
+/* itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);*/
#endif
UNBLOCK_CHILD (oset);
realloc_jobs_list ();
#ifdef DEBUG
- itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+/* itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0); */
#endif
return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
if (sigchld == 0)
longjmp (wait_intr_buf, 1);
}
+ /* If not in posix mode and not executing the wait builtin, queue the
+ signal for later handling. Run the trap immediately if we are
+ executing the wait builtin, but don't break out of `wait'. */
else if (sigchld) /* called from signal handler */
queue_sigchld_trap (children_exited);
- else
+ else if (running_trap)
+ queue_sigchld_trap (children_exited);
+ else if (this_shell_builtin == wait_builtin)
run_sigchld_trap (children_exited);
+ else
+ queue_sigchld_trap (children_exited);
}
/* We have successfully recorded the useful information about this process
subst_assign_varlist = (WORD_LIST *)NULL;
the_pipeline = (PROCESS *)NULL;
+ running_trap = SIGCHLD + 1;
+
set_impossible_sigchld_trap ();
jobs_list_frozen = 1;
for (i = 0; i < nchild; i++)
}
run_unwind_frame ("SIGCHLD trap");
+ running_trap = 0;
}
/* Function to call when you want to notify people of changes
# define NULL 0
#endif
-#if !defined (__STRING)
+#if !defined (CPP_STRING)
# if defined (HAVE_STRINGIZE)
-# define __STRING(x) #x
+# define CPP_STRING(x) #x
# else
-# define __STRING(x) "x"
+# define CPP_STRING(x) "x"
# endif /* !HAVE_STRINGIZE */
#endif /* !__STRING */
# define _(x) x
#endif
+#include <signal.h>
+
+extern void _malloc_block_signals __P((sigset_t *, sigset_t *));
+extern void _malloc_unblock_signals __P((sigset_t *, sigset_t *));
+
#endif /* _IMALLOC_H */
#define ASSERT(p) \
do \
{ \
- if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, __STRING(p), file, line); \
+ if (!(p)) xbotch((PTR_T)0, ERR_ASSERT_FAILED, CPP_STRING(p), file, line); \
} \
while (0)
#endif /* !HAVE_DECL_SBRK */
#ifdef SHELL
-extern int interrupt_immediately;
+extern int interrupt_immediately, running_trap;
extern int signal_is_trapped __P((int));
#endif
busy[nbuck] = 0;
}
-static void
-block_signals (setp, osetp)
+void
+_malloc_block_signals (setp, osetp)
sigset_t *setp, *osetp;
{
#ifdef HAVE_POSIX_SIGNALS
#endif
}
-static void
-unblock_signals (setp, osetp)
+void
+_malloc_unblock_signals (setp, osetp)
sigset_t *setp, *osetp;
{
#ifdef HAVE_POSIX_SIGNALS
/* Block all signals in case we are executed from a signal handler. */
blocked_sigs = 0;
#ifdef SHELL
- if (interrupt_immediately || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
#endif
{
- block_signals (&set, &oset);
+ _malloc_block_signals (&set, &oset);
blocked_sigs = 1;
}
morecore_done:
if (blocked_sigs)
- unblock_signals (&set, &oset);
+ _malloc_unblock_signals (&set, &oset);
}
static void
#include "imalloc.h"
#include "table.h"
+#ifdef SHELL
+extern int interrupt_immediately, running_trap;
+extern int signal_is_trapped __P((int));
+#endif
+
extern int malloc_register;
#ifdef MALLOC_REGISTER
int line;
{
mr_table_t *tentry;
+ sigset_t set, oset;
+ int blocked_sigs;
+
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+#ifdef SHELL
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+#endif
+ {
+ _malloc_block_signals (&set, &oset);
+ blocked_sigs = 1;
+ }
tentry = find_entry (mem, FIND_ALLOC);
{
/* oops. table is full. punt. */
fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
return;
}
if (tentry != &mem_overflow)
table_allocated++;
+
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
}
void
int line;
{
mr_table_t *tentry;
+ sigset_t set, oset;
+ int blocked_sigs;
+
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+#ifdef SHELL
+ if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD))
+#endif
+ {
+ _malloc_block_signals (&set, &oset);
+ blocked_sigs = 1;
+ }
tentry = find_entry (mem, FIND_EXIST);
if (tentry == 0)
#if 0
fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
#endif
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
return;
}
if (tentry->flags & MT_FREE)
if (tentry != &mem_overflow)
table_allocated--;
+
+ if (blocked_sigs)
+ _malloc_unblock_signals (&set, &oset);
}
/* If we ever add more flags, this will require changes. */
{
nval = atoi (value);
if (nval < 0)
- return 1;
+ {
+ unstifle_history ();
+ return 0;
+ }
}
stifle_history (nval);
return 0;
.\" Case Western Reserve University
.\" chet@ins.CWRU.Edu
.\"
-.\" Last Change: Sat Aug 28 18:56:32 EDT 2010
+.\" Last Change: Thu Nov 15 21:02:20 EST 2012
.\"
-.TH READLINE 3 "2010 August 28" "GNU Readline 6.2"
+.TH READLINE 3 "2012 November 15" "GNU Readline 6.2"
.\"
.\" File Name macro. This used to be `.PN', for Path Name,
.\" but Sun doesn't seem to like that very much.
or \fBnext-history\fP.
.TP
.B history\-size (0)
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
+Set the maximum number of history entries saved in the history list.
+If set to zero, any existing history entries are deleted and no new entries
+are saved.
+If set to a value less than zero, the number of history entries is not
+limited.
+By default, the number of history entries is not limited.
.TP
.B horizontal\-scroll\-mode (Off)
When set to \fBOn\fP, makes readline use a single line for display,
@item history-size
@vindex history-size
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
+Set the maximum number of history entries saved in the history list.
+If set to zero, any existing history entries are deleted and no new entries
+are saved.
+If set to a value less than zero, the number of history entries is not
+limited.
+By default, the number of history entries is not limited.
@item horizontal-scroll-mode
@vindex horizontal-scroll-mode
@set EDITION 6.2
@set VERSION 6.2
-@set UPDATED 23 September 2012
-@set UPDATED-MONTH September 2012
+@set UPDATED 15 November 2012
+@set UPDATED-MONTH November 2012
-@set LASTCHANGE Sun Sep 23 19:19:18 EDT 2012
+@set LASTCHANGE Thu Nov 15 21:03:04 EST 2012
var_is_set = temp != (char *)0;
var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
+ /* XXX - this may not need to be restricted to special variables */
+ if (check_nullness)
+ var_is_null |= var_is_special && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp);
/* Get the rest of the stuff inside the braces. */
if (c && c != RBRACE)
# through bash-4.2
${THIS_SH} ./dollar-at5.sub
+# tests for expansions of $* when $1 == ""; problem through bash-4.2
+${THIS_SH} ./dollar-star6.sub
+
exit 0
--- /dev/null
+set -- ""
+
+recho "A${*:-w}R"
+recho "A${*-w}R"
+recho "A${*}R"
set y zcx c2 c3
0
declare -a c='([0]="y" [1]="zcx" [2]="c2" [3]="c3")'
+argv[1] = <AwR>
+argv[1] = <AR>
+argv[1] = <AR>
trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
(sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
{
+ sigmodes[SIGCHLD] |= SIG_INPROGRESS;
run_sigchld_trap (pending_traps[sig]); /* use as counter */
+ sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
+ }
+ else if (sig == SIGCHLD &&
+ trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
+ (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
+ {
+ /* This can happen when run_pending_traps is called while
+ running a SIGCHLD trap handler. */
+ UNBLOCK_SIGNAL (oset);
+ continue; /* XXX */
}
#endif
else if (trap_list[sig] == (char *)DEFAULT_SIG ||
wait_signal_received = sig;
if (interrupt_immediately)
{
-itrace("trap_handler: calling longjmp to wait_intr_buf: sig = %d", sig);
+itrace("trap_handler: interrupt_immediately = 1: calling longjmp to wait_intr_buf: sig = %d", sig);
longjmp (wait_intr_buf, 1);
}
}
int nchild;
{
if (nchild > 0)
- pending_traps[SIGCHLD] += nchild;
+ {
+ catch_flag = 1;
+ pending_traps[SIGCHLD] += nchild;
+ trapped_signal_received = SIGCHLD;
+ }
}
#endif /* JOB_CONTROL && SIGCHLD */