mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 00:49:57 +02:00
fix minor errors uncovered by address sanitizer; work around android issue with read -e -u; fix minor memory leaks; make spell-correct-shellword work with negative arguments; fix readline change-case on invalid multibyte character
This commit is contained in:
@@ -9454,3 +9454,70 @@ pathexp.c
|
||||
integer underflow
|
||||
From a report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
5/20
|
||||
----
|
||||
lib/readline/kill.c
|
||||
- _rl_bracketed_text: make sure buf is null-terminated even if
|
||||
rl_read_key() returns an error
|
||||
From a report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
builtins/read.def
|
||||
- read_builtin: if -u and -e are both supplied, dup the file descriptor
|
||||
supplied as an argument to -u and use it in the new FILE * to pass
|
||||
to readline as rl_instream. Works around an android problem with
|
||||
stdio and application-managed file descriptors
|
||||
Report and patch from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
5/21
|
||||
----
|
||||
lib/sh/spell.c
|
||||
- mindist: don't check best unless we set it
|
||||
Report and patch from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
jobs.c
|
||||
- make_child: if FORK_NOJOB is in the flags argument, don't call
|
||||
setpgid to set the child's process group in either the parent or
|
||||
child
|
||||
- alloc_process,dispose_process: allocate and deallocate a PROCESS;
|
||||
changed callers
|
||||
|
||||
subst.c
|
||||
- command_substitute: call cleanup_the_pipeline after waiting for
|
||||
the command substitution process, since we allocated it
|
||||
|
||||
5/22
|
||||
----
|
||||
lib/readline/text.c
|
||||
- rl_execute_named_command: fix a leak if the command name is null or
|
||||
the bound function doesn't return (rl_abort)
|
||||
Report and patch from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
bashline.c
|
||||
- command_word_completion_function: free directory_part if it's left
|
||||
over from a previous completion
|
||||
- command_subst_completion_function: free contents of match list left
|
||||
over from previous completion
|
||||
- bash_spell_correct_shellword: free text if it's "" before returning
|
||||
- build_history_completion_array: only call qsort if there's actually
|
||||
something in the array to sort
|
||||
Report and patches from Grisha Levit <grishalevit@gmail.com>
|
||||
- bash_spell_correct_shellword: fix bug where we would correct the
|
||||
previous word if we start on the first character of a word
|
||||
- bash_spell_correct_shellword: make negative argument counts work
|
||||
backwards, correcting words before point
|
||||
Report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
5/23
|
||||
----
|
||||
lib/readline/text.c
|
||||
- rl_change_case: if mbrtowc returns -1 or -2, jump to changing case
|
||||
for a single character, since _rl_find_next_mbchar_internal() will
|
||||
treat an invalid multibyte character as a sequence of bytes
|
||||
Report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
5/25
|
||||
----
|
||||
execute_cmd.c
|
||||
- shell_execve: fix typo in code that chops \r off the end of the #!
|
||||
interpreter
|
||||
Report and fix from Collin Funk <collin.funk1@gmail.com>
|
||||
|
||||
+47
-7
@@ -1328,14 +1328,45 @@ bash_transpose_shellwords (int count, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Directory name spelling correction on the current word (not shellword).
|
||||
COUNT > 1 is not exactly correct yet. */
|
||||
/* Directory name spelling correction on the current or previous shellword. */
|
||||
static int
|
||||
bash_spell_correct_shellword (int count, int key)
|
||||
{
|
||||
int wbeg, wend;
|
||||
int wbeg, wend, n, p;
|
||||
char *text, *newdir;
|
||||
|
||||
/* If we have a negative count, move back that many shellwords and then
|
||||
move forward. Do it one at a time so we get an accurate count of the
|
||||
number of words we moved back -- we only want to correct that many. */
|
||||
if (count < 0)
|
||||
{
|
||||
n = 0;
|
||||
while (rl_point > 0 && count++)
|
||||
{
|
||||
p = rl_point;
|
||||
bash_backward_shellword (1, key);
|
||||
/* We probably moved to column 0 with leading spaces on the line */
|
||||
if (rl_point == 0 && WORDDELIM (rl_line_buffer[rl_point]))
|
||||
{
|
||||
rl_point = p;
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
count = n;
|
||||
}
|
||||
else if (WORDDELIM (rl_line_buffer[rl_point])) /* count > 0 */
|
||||
{
|
||||
/* between words with a positive count, move forward to word start */
|
||||
while (rl_point < rl_end && WORDDELIM (rl_line_buffer[rl_point]))
|
||||
rl_point++; /* word delims are single-byte characters */
|
||||
}
|
||||
|
||||
/* First make sure we're at the end of the word we want to begin with
|
||||
so the initial bash_backward_shellword works right. */
|
||||
if (rl_point < rl_end && WORDDELIM (rl_line_buffer[rl_point]) == 0)
|
||||
bash_forward_shellword (1, key);
|
||||
|
||||
while (count)
|
||||
{
|
||||
bash_backward_shellword (1, key);
|
||||
@@ -1348,7 +1379,10 @@ bash_spell_correct_shellword (int count, int key)
|
||||
|
||||
text = rl_copy_text (wbeg, wend);
|
||||
if (text == 0 || *text == 0)
|
||||
break;
|
||||
{
|
||||
FREE (text);
|
||||
break;
|
||||
}
|
||||
|
||||
newdir = dirspell (text);
|
||||
if (newdir)
|
||||
@@ -1371,7 +1405,7 @@ bash_spell_correct_shellword (int count, int key)
|
||||
count--;
|
||||
|
||||
if (count)
|
||||
bash_forward_shellword (1, key); /* XXX */
|
||||
bash_forward_shellword (1, key); /* XXX */
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2002,6 +2036,12 @@ command_word_completion_function (const char *hint_text, int state)
|
||||
glob_matches = (char **)NULL;
|
||||
}
|
||||
|
||||
if (directory_part)
|
||||
{
|
||||
free (directory_part);
|
||||
directory_part = (char *)NULL;
|
||||
}
|
||||
|
||||
globpat = completion_glob_pattern (hint_text);
|
||||
|
||||
/* If this is an absolute program name, do not check it against
|
||||
@@ -2451,7 +2491,7 @@ command_subst_completion_function (const char *text, int state)
|
||||
filename_text = savestring (text);
|
||||
if (matches)
|
||||
{
|
||||
free (matches);
|
||||
strvec_dispose (matches);
|
||||
matches = (char **)NULL;
|
||||
}
|
||||
|
||||
@@ -3716,7 +3756,7 @@ build_history_completion_array (void)
|
||||
}
|
||||
|
||||
/* Sort the complete list of tokens. */
|
||||
if (dabbrev_expand_active == 0)
|
||||
if (harry_len > 1 && dabbrev_expand_active == 0)
|
||||
qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
|
||||
}
|
||||
}
|
||||
|
||||
+30
-3
@@ -201,6 +201,19 @@ read_builtin_timeout (int fd)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
reset_rl_instream (FILE *save_instream)
|
||||
{
|
||||
fclose (rl_instream);
|
||||
rl_instream = save_instream;
|
||||
}
|
||||
|
||||
void
|
||||
uw_reset_rl_instream (void *fp)
|
||||
{
|
||||
reset_rl_instream (fp);
|
||||
}
|
||||
|
||||
/* Read the value of the shell variables whose names follow.
|
||||
The reading is done from the current input stream, whatever
|
||||
that may be. Successive words of the input line are assigned
|
||||
@@ -613,12 +626,26 @@ read_builtin (WORD_LIST *list)
|
||||
save_instream = 0;
|
||||
if (edit && fd != 0)
|
||||
{
|
||||
int fd2;
|
||||
FILE *fp2;
|
||||
|
||||
if ((fd2 = dup (fd)) < 0 || (fp2 = fdopen (fd2, "r")) == 0)
|
||||
{
|
||||
builtin_error ("%d: %s", fd, strerror (errno));
|
||||
if (fd2 >= 0)
|
||||
close (fd2);
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (bash_readline_initialized == 0)
|
||||
initialize_readline ();
|
||||
|
||||
unwind_protect_var (rl_instream);
|
||||
save_instream = rl_instream;
|
||||
rl_instream = fdopen (fd, "r");
|
||||
rl_instream = fp2;
|
||||
add_unwind_protect (uw_reset_rl_instream, save_instream);
|
||||
|
||||
fd = fd2;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -896,7 +923,7 @@ add_char:
|
||||
|
||||
#if defined (READLINE)
|
||||
if (save_instream)
|
||||
rl_instream = save_instream; /* can't portably free it */
|
||||
reset_rl_instream (save_instream);
|
||||
#endif
|
||||
|
||||
discard_unwind_frame ("read_builtin");
|
||||
|
||||
+4
-1
@@ -154,7 +154,10 @@ source_builtin (WORD_LIST *list)
|
||||
#else
|
||||
if (posixly_correct == 0 && (spath = path_value ("BASH_SOURCE_PATH", 1)))
|
||||
#endif
|
||||
filename = find_in_path (list->word->word, spath, FS_READABLE);
|
||||
{
|
||||
filename = find_in_path (list->word->word, spath, FS_READABLE);
|
||||
search_cwd = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
filename = find_path_file (list->word->word);
|
||||
|
||||
+2
-1
@@ -2326,7 +2326,8 @@ inode change time, and number of blocks, respectively.
|
||||
For example, a value of \fI\-mtime\fP sorts the results in descending
|
||||
order by modification time (newest first).
|
||||
A sort specifier of \fInosort\fP disables sorting completely; the results
|
||||
are returned in the order they are read from the file system.
|
||||
are returned in the order they are read from the file system,
|
||||
and any leading \fI+\fP or \fI\-\fP is ignored.
|
||||
If the sort specifier is missing, it defaults to \fIname\fP,
|
||||
so a value of \fI+\fP is equivalent to the null string,
|
||||
and a value of \fI-\fP sorts by name in descending order.
|
||||
|
||||
+2
-1
@@ -6694,7 +6694,8 @@ For example, a value of @code{-mtime} sorts the results in descending
|
||||
order by modification time (newest first).
|
||||
|
||||
A sort specifier of @samp{nosort} disables sorting completely; the results
|
||||
are returned in the order they are read from the file system.
|
||||
are returned in the order they are read from the file system,
|
||||
and any leading @samp{-} is ignored.
|
||||
|
||||
If the sort specifier is missing, it defaults to @var{name},
|
||||
so a value of @samp{+} is equivalent to the null string,
|
||||
|
||||
+3
-3
@@ -1392,13 +1392,13 @@ print_formatted_time (FILE *fp, char *format,
|
||||
static int
|
||||
time_command (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, struct fd_bitmap *fds_to_close)
|
||||
{
|
||||
int rv, posix_time, old_flags, nullcmd, code;
|
||||
int rv, posix_time, nullcmd, code;
|
||||
time_t rs, us, ss; /* seconds */
|
||||
long rsf, usf, ssf; /* microseconds */
|
||||
int cpu;
|
||||
char *time_format;
|
||||
volatile procenv_t save_top_level;
|
||||
volatile int old_subshell;
|
||||
volatile int old_subshell, old_flags;
|
||||
|
||||
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
|
||||
struct timeval real, user, sys;
|
||||
@@ -6128,7 +6128,7 @@ shell_execve (char *command, char **args, char **env)
|
||||
interp = getinterp (sample, sample_len, (int *)NULL);
|
||||
ilen = strlen (interp);
|
||||
errno = i;
|
||||
if (interp > 0 && interp[ilen - 1] == '\r')
|
||||
if (ilen > 0 && interp[ilen - 1] == '\r')
|
||||
{
|
||||
interp = xrealloc (interp, ilen + 2);
|
||||
interp[ilen - 1] = '^';
|
||||
|
||||
@@ -216,6 +216,9 @@ volatile pid_t last_asynchronous_pid = NO_PID;
|
||||
/* The pipeline currently being built. */
|
||||
PROCESS *the_pipeline = (PROCESS *)NULL;
|
||||
|
||||
/* We are forking this pipeline (process) to perform a command substitution. */
|
||||
PROCESS *comsub_pipeline = (PROCESS *)NULL;
|
||||
|
||||
/* If this is non-zero, do job control. */
|
||||
int job_control = 1;
|
||||
|
||||
@@ -643,8 +646,9 @@ stop_pipeline (int async, COMMAND *deferred)
|
||||
the_pipeline = (PROCESS *)NULL;
|
||||
newjob->pgrp = pipeline_pgrp;
|
||||
|
||||
/* Invariant: if the shell is executing a command substitution,
|
||||
pipeline_pgrp == shell_pgrp. Other parts of the shell assume this. */
|
||||
/* Invariant: if the shell is executing a command substitution when
|
||||
job control is enabled, pipeline_pgrp == shell_pgrp.
|
||||
Other parts of the shell assume this. */
|
||||
if (pipeline_pgrp != shell_pgrp)
|
||||
pipeline_pgrp = 0;
|
||||
|
||||
@@ -1473,6 +1477,28 @@ nohup_job (int job_index)
|
||||
temp->flags |= J_NOHUP;
|
||||
}
|
||||
|
||||
PROCESS *
|
||||
alloc_process (char *name, pid_t pid)
|
||||
{
|
||||
PROCESS *t;
|
||||
|
||||
t = (PROCESS *)xmalloc (sizeof (PROCESS));
|
||||
t->pid = pid;
|
||||
WSTATUS (t->status) = 0;
|
||||
t->running = PS_RUNNING; /* default */
|
||||
t->command = name;
|
||||
t->next = (PROCESS *)0;
|
||||
|
||||
return (t);
|
||||
}
|
||||
|
||||
void
|
||||
dispose_process (PROCESS *t)
|
||||
{
|
||||
FREE (t->command);
|
||||
free (t);
|
||||
}
|
||||
|
||||
/* Get rid of the data structure associated with a process chain. */
|
||||
int
|
||||
discard_pipeline (PROCESS *chain)
|
||||
@@ -1485,8 +1511,7 @@ discard_pipeline (PROCESS *chain)
|
||||
do
|
||||
{
|
||||
next = this->next;
|
||||
FREE (this->command);
|
||||
free (this);
|
||||
dispose_process (this);
|
||||
n++;
|
||||
this = next;
|
||||
}
|
||||
@@ -1516,12 +1541,8 @@ add_process (char *name, pid_t pid)
|
||||
}
|
||||
#endif
|
||||
|
||||
t = (PROCESS *)xmalloc (sizeof (PROCESS));
|
||||
t = alloc_process (name, pid);
|
||||
t->next = the_pipeline;
|
||||
t->pid = pid;
|
||||
WSTATUS (t->status) = 0;
|
||||
t->running = PS_RUNNING;
|
||||
t->command = name;
|
||||
the_pipeline = t;
|
||||
|
||||
if (t->next == 0)
|
||||
@@ -1542,13 +1563,11 @@ append_process (char *name, pid_t pid, int status, int jid)
|
||||
{
|
||||
PROCESS *t, *p;
|
||||
|
||||
t = (PROCESS *)xmalloc (sizeof (PROCESS));
|
||||
t->next = (PROCESS *)NULL;
|
||||
t->pid = pid;
|
||||
t = alloc_process (name, pid);
|
||||
|
||||
/* set process exit status using offset discovered by configure */
|
||||
t->status = (status & 0xff) << WEXITSTATUS_OFFSET;
|
||||
t->running = PS_DONE;
|
||||
t->command = name;
|
||||
|
||||
js.c_reaped++; /* XXX */
|
||||
|
||||
@@ -2267,6 +2286,7 @@ make_child (char *command, int flags)
|
||||
pipeline_pgrp = mypid;
|
||||
|
||||
/* Check for running command in backquotes. */
|
||||
/* XXX - do this if (flags & FORK_NOJOB)? */
|
||||
if (pipeline_pgrp == shell_pgrp)
|
||||
ignore_tty_job_signals ();
|
||||
else
|
||||
@@ -2280,7 +2300,7 @@ make_child (char *command, int flags)
|
||||
this would have for the first child) is an error. Section
|
||||
B.4.3.3, p. 237 also covers this, in the context of job control
|
||||
shells. */
|
||||
if (setpgid (mypid, pipeline_pgrp) < 0)
|
||||
if ((flags & FORK_NOJOB) == 0 && setpgid (mypid, pipeline_pgrp) < 0)
|
||||
sys_error (_("child setpgid (%ld to %ld)"), (long)mypid, (long)pipeline_pgrp);
|
||||
|
||||
/* By convention (and assumption above), if
|
||||
@@ -2344,7 +2364,8 @@ make_child (char *command, int flags)
|
||||
the POSIX 1003.1 standard, where it discusses job control and
|
||||
shells. It is done to avoid possible race conditions. (Ref.
|
||||
1003.1 Rationale, section B.4.3.3, page 236). */
|
||||
setpgid (pid, pipeline_pgrp);
|
||||
if ((flags & FORK_NOJOB) == 0)
|
||||
setpgid (pid, pipeline_pgrp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3964,7 +3985,12 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc
|
||||
if (child == 0)
|
||||
{
|
||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||
js.c_reaped++;
|
||||
{
|
||||
js.c_reaped++;
|
||||
js.c_totreaped++;
|
||||
if (pid == wpid) /* but we're waiting for it?? */
|
||||
internal_debug ("waitchld: pid == wpid but child == 0");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,7 @@ struct procchain {
|
||||
#define FORK_ASYNC 1 /* background process */
|
||||
#define FORK_NOJOB 2 /* don't put process in separate pgrp */
|
||||
#define FORK_NOTERM 4 /* don't give terminal to any pgrp */
|
||||
#define FORK_COMSUB 8 /* command or process substitution */
|
||||
|
||||
/* System calls. */
|
||||
#if !defined (HAVE_UNISTD_H)
|
||||
@@ -239,6 +240,8 @@ extern void save_pipeline (int);
|
||||
extern PROCESS *restore_pipeline (int);
|
||||
extern void start_pipeline (void);
|
||||
extern int stop_pipeline (int, COMMAND *);
|
||||
extern PROCESS *alloc_process (char *, pid_t);
|
||||
extern void dispose_process (PROCESS *);
|
||||
extern int discard_pipeline (PROCESS *);
|
||||
extern void append_process (char *, pid_t, int, int);
|
||||
|
||||
|
||||
+3
-6
@@ -737,12 +737,9 @@ _rl_bracketed_text (size_t *lenp)
|
||||
}
|
||||
RL_UNSETSTATE (RL_STATE_MOREINPUT);
|
||||
|
||||
if (c >= 0)
|
||||
{
|
||||
if (len == cap)
|
||||
buf = xrealloc (buf, cap + 1);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
if (len == cap)
|
||||
buf = xrealloc (buf, cap + 1);
|
||||
buf[len] = '\0';
|
||||
|
||||
if (lenp)
|
||||
*lenp = len;
|
||||
|
||||
+20
-6
@@ -1449,6 +1449,7 @@ rl_change_case (int count, int op)
|
||||
int start, next, end;
|
||||
int inword, nc, nop;
|
||||
WCHAR_T c;
|
||||
unsigned char uc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
WCHAR_T wc, nwc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
@@ -1503,7 +1504,9 @@ rl_change_case (int count, int op)
|
||||
characters */
|
||||
if (MB_CUR_MAX == 1 || rl_byte_oriented)
|
||||
{
|
||||
nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
|
||||
change_singlebyte:
|
||||
uc = c;
|
||||
nc = (nop == UpCase) ? _rl_to_upper (uc) : _rl_to_lower (uc);
|
||||
rl_line_buffer[start] = nc;
|
||||
}
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -1511,9 +1514,16 @@ rl_change_case (int count, int op)
|
||||
{
|
||||
m = MBRTOWC (&wc, rl_line_buffer + start, end - start, &mps);
|
||||
if (MB_INVALIDCH (m))
|
||||
wc = (WCHAR_T)rl_line_buffer[start];
|
||||
{
|
||||
c = rl_line_buffer[start];
|
||||
next = start + 1; /* potentially redundant */
|
||||
goto change_singlebyte;
|
||||
}
|
||||
else if (MB_NULLWCH (m))
|
||||
wc = L'\0';
|
||||
{
|
||||
start = next; /* don't bother with null wide characters */
|
||||
continue;
|
||||
}
|
||||
nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
|
||||
if (nwc != wc) /* just skip unchanged characters */
|
||||
{
|
||||
@@ -2355,8 +2365,13 @@ rl_execute_named_command (int count, int key)
|
||||
|
||||
command = _rl_read_command_name ();
|
||||
if (command == 0 || *command == '\0')
|
||||
return 1;
|
||||
if (func = rl_named_function (command))
|
||||
{
|
||||
free (command);
|
||||
return 1;
|
||||
}
|
||||
func = rl_named_function (command);
|
||||
free (command);
|
||||
if (func)
|
||||
{
|
||||
int prev, ostate;
|
||||
|
||||
@@ -2375,6 +2390,5 @@ rl_execute_named_command (int count, int key)
|
||||
r = 1;
|
||||
}
|
||||
|
||||
free (command);
|
||||
return r;
|
||||
}
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ mindist(const char *dir, char *guess, char *best)
|
||||
(void)closedir(fd);
|
||||
|
||||
/* Don't return `.' */
|
||||
if (best[0] == '.' && best[1] == '\0')
|
||||
if (dist != 3 && best[0] == '.' && best[1] == '\0')
|
||||
dist = 3;
|
||||
return dist;
|
||||
}
|
||||
|
||||
@@ -751,7 +751,9 @@ globsort_namecmp (char **s1, char **s2)
|
||||
}
|
||||
|
||||
/* Generic transitive comparison of two numeric values for qsort */
|
||||
#define GENCMP(a,b) (a < b ? -1 : (a > b ? 1 : 0))
|
||||
/* #define GENCMP(a,b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0)) */
|
||||
/* A clever idea from gnulib */
|
||||
#define GENCMP(a,b) (((a) > (b)) - ((a) < (b)))
|
||||
|
||||
static int
|
||||
globsort_sizecmp (struct globsort_t *g1, struct globsort_t *g2)
|
||||
|
||||
@@ -7278,7 +7278,10 @@ command_substitute (char *string, int quoted, int flags)
|
||||
for example). */
|
||||
if ((subshell_environment & (SUBSHELL_FORK|SUBSHELL_PIPE)) == 0)
|
||||
pipeline_pgrp = shell_pgrp;
|
||||
/* this can happen if we're performing word expansion in the second or
|
||||
subsequent commands in a pipeline */
|
||||
cleanup_the_pipeline ();
|
||||
/* at this point, the_pipeline is NULL */
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
old_async_pid = last_asynchronous_pid;
|
||||
@@ -7491,6 +7494,11 @@ command_substitute (char *string, int quoted, int flags)
|
||||
|
||||
CHECK_TERMSIG;
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* this is the pipeline we allocated for this command substitution */
|
||||
cleanup_the_pipeline ();
|
||||
#endif
|
||||
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = istring;
|
||||
ret->flags = tflag;
|
||||
|
||||
Reference in New Issue
Block a user