closing right bracket, rescan it from just after the opening
bracket without treating it as a bracket expression. Bug report
from Stephane Chazelas <stephane.chazelas@gmail.com>
+
+ 3/9
+ ---
+subst.c
+ - process_substitute: keep the last pipeline created to run a process
+ substitution in LAST_PROCSUB_CHILD; discard it when another one is
+ created
+
+jobs.[ch]
+ - discard_pipeline: now global, so process_substitute can call it
+
+jobs.c
+ - last_procsub_child: new variable, set and modified only by the process
+ substitution code
+ - find_pipeline: if the requested pid is in LAST_PROCSUB_CHILD, return it;
+ analogous to the way this code handles the_pipeline
+ - waitchld: if we find a child via find_pipeline that is a part of the
+ last process substitution child, mark that child appropriately. If
+ the child is dead, add it to the bgp list. This and the previous change
+ allow waiting for the most recent process substitution (the one
+ corresponding to $!). Original report from Stephane Chazelas
+ <stephane.chazelas@gmail.com>
+
+ 3/10
+ ----
+arrayfunc.c
+ - unbind_array_element: make sure skipsubscript() doesn't try to parse
+ embedded quotes in the subscript, since this has already been through
+ one round of word expansion before calling the unset builtin. (This
+ function is only called by the unset builtin). Fixes bug reported by
+ <vampyrebat@gmail.com>
/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
-/* Copyright (C) 2001-2011 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
char *akey;
ARRAY_ELEMENT *ae;
- len = skipsubscript (sub, 0, 0);
+ len = skipsubscript (sub, 0, (var && assoc_p(var)));
if (sub[len] != ']' || len == 0)
{
builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
exits from get_tty_state(). */
int check_window_size = CHECKWINSIZE_DEFAULT;
+PROCESS *last_procsub_child = (PROCESS *)NULL;
+
/* Functions local to this file. */
static sighandler wait_sigint_handler __P((int));
static int processes_in_job __P((int));
static void realloc_jobs_list __P((void));
static int compact_jobs_list __P((int));
-static int discard_pipeline __P((PROCESS *));
static void add_process __P((char *, pid_t));
static void print_pipeline __P((PROCESS *, int, int, FILE *));
static void pretty_print_job __P((int, int, FILE *));
UNBLOCK_CHILD (oset);
}
-void
+PROCESS *
restore_pipeline (discard)
int discard;
{
UNBLOCK_CHILD (oset);
if (discard && old_pipeline)
- discard_pipeline (old_pipeline);
+ {
+ discard_pipeline (old_pipeline);
+ return ((PROCESS *)NULL);
+ }
+ return old_pipeline;
}
/* Start building a pipeline. */
}
/* Get rid of the data structure associated with a process chain. */
-static int
+int
discard_pipeline (chain)
register PROCESS *chain;
{
}
while (p != the_pipeline);
}
+ /* Now look in the last process substitution pipeline, since that sets $! */
+ if (last_procsub_child)
+ {
+ p = last_procsub_child;
+ do
+ {
+ /* Return it if we found it. Don't ever return a recycled pid. */
+ if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
+ return (p);
+
+ p = p->next;
+ }
+ while (p != last_procsub_child);
+ }
job = find_job (pid, alive_only, &p);
if (jobp)
js.c_reaped++;
}
+#if defined (PROCESS_SUBSTITUTION)
+ /* XXX - should we make this unconditional and not depend on last procsub? */
+ if (child && child == last_procsub_child && child->running == PS_DONE)
+ bgp_add (child->pid, process_exit_status (child->status)); /* XXX */
+#endif
+
if (job == NO_JOB)
continue;
extern void stop_making_children __P((void));
extern void cleanup_the_pipeline __P((void));
extern void save_pipeline __P((int));
-extern void restore_pipeline __P((int));
+extern PROCESS *restore_pipeline __P((int));
extern void start_pipeline __P((void));
extern int stop_pipeline __P((int, COMMAND *));
+extern int discard_pipeline __P((PROCESS *));
extern void append_process __P((char *, pid_t, int, int));
extern void delete_job __P((int, int));
extern int tempenv_assign_error;
extern int builtin_ignoring_errexit;
+#if defined (JOB_CONTROL) && defined (PROCESS_SUBSTITUTION)
+extern PROCESS *last_procsub_child;
+#endif
+
#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
extern wchar_t *wcsdup __P((const wchar_t *));
#endif
if (pid > 0)
{
#if defined (JOB_CONTROL)
- restore_pipeline (1);
+ if (last_procsub_child)
+ {
+ discard_pipeline (last_procsub_child);
+ last_procsub_child = (PROCESS *)NULL;
+ }
+ last_procsub_child = restore_pipeline (0);
#endif
#if !defined (HAVE_DEV_FD)