From 3235014e5b3d227ccd617b0be72d897eb476d23d Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 20 Apr 2020 10:11:53 -0400 Subject: [PATCH] commit bash-20200417 snapshot --- CWRU/CWRU.chlog | 67 +++++++++++++++++++++++++++++++++++++++++ assoc.h | 42 ++++++++++++++------------ builtins/read.def | 2 ++ doc/bash.1 | 8 +++-- doc/bashref.texi | 3 ++ doc/version.texi | 4 +-- execute_cmd.c | 36 ++++++++++++---------- hashcmd.h | 14 ++++----- jobs.c | 17 ++++++----- jobs.h | 22 ++++++++------ nojobs.c | 3 +- subst.c | 32 +++++++++----------- tests/RUN-ONE-TEST | 2 +- tests/appendop.right | 4 +-- tests/array.right | 8 ++--- tests/assoc.right | 72 ++++++++++++++++++++++---------------------- tests/new-exp.right | 2 +- tests/type.right | 2 +- tests/varenv.right | 2 +- variables.c | 6 ++-- 20 files changed, 216 insertions(+), 132 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 9e668be5c..9a51b0656 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8009,3 +8009,70 @@ examples/loadables/cut.c - lcut: new builtin that does what cut does but on a string supplied as an argument (only one string for now) + 4/17 + ---- +jobs.h + - FORK_SYNC,FORK_ASYNC,FORK_NOJOB: new flag values for the second + argument to make_child + +jobs.c + - make_child: now takes a set of flags as the second argument + +execute_cmd.c + - make_child: change callers to pass FORK_ASYNC instead of a non-zero + value as the second argument + +subst.c + - make_child: change callers to pass FORK_ASYNC instead of a non-zero + value as the second argument + +doc/{bash.1,bashref.texi} + - document that the words in a compound array assignment undergo all + the shell word expansions, including filename generation and word + splitting. From a report from E. Choroba + + 4/18 + ---- +subst.c + - command_substitute: use JOB_CONTROL instead of INTERACTIVE in the + test to determine whether or not to give the terminal back to + pipeline_pgrp + +jobs.c + - make_child: if FORK_NOTERM is set in the flags argument, don't call + give_terminal_to + +{jobs,nojobs}.c,jobs.h + - wait_for: now takes a second argument, a flags word + +{execute_cmd,subst}.c + - wait_for: change all callers to add second argument to wait_for + +jobs.c + - wait_for: if JWAIT_NOTERM is set in the flags argument, don't call + give_terminal_to + + 4/19 + ---- +subst.c + - command_substitute: block SIGINT around call to read_comsub, so we + let any interrupts affect the command substitution. Fixes issue + reported by DALECKI Léo + +hashcmd.h + - FILENAME_HASH_BUCKETS: increase to 256 + +assoc.h + - ASSOC_HASH_BUCKETS: new define, set to 1024 + +variables.c + - make_new_assoc_variable,make_local_assoc_variable: call assoc_create + with ASSOC_HASH_BUCKETS as argument. This changes the hash function + and how the array keys are ordered (which is not guaranteed) + +builtins/read.def + - read_builtin: in posix mode, or if the read call returns -1/EINTR, + don't call run_pending_traps until the read command returns. This + allows a trap action to see the same exit status that the read + builtin would return when it exits on a signal (e.g., SIGINT == 130). + From a suggestion by diff --git a/assoc.h b/assoc.h index b5a263975..78ec07386 100644 --- a/assoc.h +++ b/assoc.h @@ -1,7 +1,7 @@ /* assoc.h -- definitions for the interface exported by assoc.c that allows the rest of the shell to manipulate associative array variables. */ -/* Copyright (C) 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -25,6 +25,8 @@ #include "stdc.h" #include "hashlib.h" +#define ASSOC_HASH_BUCKETS 1024 + #define assoc_empty(h) ((h)->nentries == 0) #define assoc_num_elements(h) ((h)->nentries) @@ -34,30 +36,30 @@ #define assoc_walk(h, f) (hash_walk((h), (f)) -extern void assoc_dispose __P((HASH_TABLE *)); -extern void assoc_flush __P((HASH_TABLE *)); +extern void assoc_dispose PARAMS((HASH_TABLE *)); +extern void assoc_flush PARAMS((HASH_TABLE *)); -extern int assoc_insert __P((HASH_TABLE *, char *, char *)); -extern PTR_T assoc_replace __P((HASH_TABLE *, char *, char *)); -extern void assoc_remove __P((HASH_TABLE *, char *)); +extern int assoc_insert PARAMS((HASH_TABLE *, char *, char *)); +extern PTR_T assoc_replace PARAMS((HASH_TABLE *, char *, char *)); +extern void assoc_remove PARAMS((HASH_TABLE *, char *)); -extern char *assoc_reference __P((HASH_TABLE *, char *)); +extern char *assoc_reference PARAMS((HASH_TABLE *, char *)); -extern char *assoc_subrange __P((HASH_TABLE *, arrayind_t, arrayind_t, int, int, int)); -extern char *assoc_patsub __P((HASH_TABLE *, char *, char *, int)); -extern char *assoc_modcase __P((HASH_TABLE *, char *, int, int)); +extern char *assoc_subrange PARAMS((HASH_TABLE *, arrayind_t, arrayind_t, int, int, int)); +extern char *assoc_patsub PARAMS((HASH_TABLE *, char *, char *, int)); +extern char *assoc_modcase PARAMS((HASH_TABLE *, char *, int, int)); -extern HASH_TABLE *assoc_quote __P((HASH_TABLE *)); -extern HASH_TABLE *assoc_quote_escapes __P((HASH_TABLE *)); -extern HASH_TABLE *assoc_dequote __P((HASH_TABLE *)); -extern HASH_TABLE *assoc_dequote_escapes __P((HASH_TABLE *)); -extern HASH_TABLE *assoc_remove_quoted_nulls __P((HASH_TABLE *)); +extern HASH_TABLE *assoc_quote PARAMS((HASH_TABLE *)); +extern HASH_TABLE *assoc_quote_escapes PARAMS((HASH_TABLE *)); +extern HASH_TABLE *assoc_dequote PARAMS((HASH_TABLE *)); +extern HASH_TABLE *assoc_dequote_escapes PARAMS((HASH_TABLE *)); +extern HASH_TABLE *assoc_remove_quoted_nulls PARAMS((HASH_TABLE *)); -extern char *assoc_to_kvpair __P((HASH_TABLE *, int)); -extern char *assoc_to_assign __P((HASH_TABLE *, int)); +extern char *assoc_to_kvpair PARAMS((HASH_TABLE *, int)); +extern char *assoc_to_assign PARAMS((HASH_TABLE *, int)); -extern WORD_LIST *assoc_to_word_list __P((HASH_TABLE *)); -extern WORD_LIST *assoc_keys_to_word_list __P((HASH_TABLE *)); +extern WORD_LIST *assoc_to_word_list PARAMS((HASH_TABLE *)); +extern WORD_LIST *assoc_keys_to_word_list PARAMS((HASH_TABLE *)); -extern char *assoc_to_string __P((HASH_TABLE *, char *, int)); +extern char *assoc_to_string PARAMS((HASH_TABLE *, char *, int)); #endif /* _ASSOC_H_ */ diff --git a/builtins/read.def b/builtins/read.def index 47715512c..18f019307 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -624,7 +624,9 @@ read_builtin (list) lastsig = LASTSIG(); if (lastsig == 0) lastsig = trapped_signal_received; +#if 0 run_pending_traps (); /* because interrupt_immediately is not set */ +#endif } else lastsig = 0; diff --git a/doc/bash.1 b/doc/bash.1 index a2b659b55..151c14cb5 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Thu Apr 9 11:50:30 EDT 2020 +.\" Last Change: Fri Apr 17 16:30:01 EDT 2020 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2020 April 9" "GNU Bash 5.0" +.TH BASH 1 "2020 April 17" "GNU Bash 5.0" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -2682,6 +2682,10 @@ Arrays are assigned to using compound assignments of the form \fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each \fIvalue\fP may be of the form [\fIsubscript\fP]=\fIstring\fP. Indexed array assignments do not require anything but \fIstring\fP. +Each \fIvalue\fP in the list is expanded using all the shell expansions +described below under +.SM +.BR EXPANSION . When assigning to indexed arrays, if the optional brackets and subscript are supplied, that index is assigned to; otherwise the index of the element assigned is the last index assigned diff --git a/doc/bashref.texi b/doc/bashref.texi index 4a57871a8..4c1111a18 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -7312,6 +7312,9 @@ the optional subscript is supplied, that index is assigned to; otherwise the index of the element assigned is the last index assigned to by the statement plus one. Indexing starts at zero. +Each @var{value} in the list undergoes all the shell expansions +described above (@pxref{Shell Expansions}). + When assigning to an associative array, the words in a compound assignment may be either assignment statements, for which the subscript is required, or a list of words that is interpreted as a sequence of alternating keys diff --git a/doc/version.texi b/doc/version.texi index 3098b9c74..cfbd58c8e 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2020 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Thu Apr 9 11:58:06 EDT 2020 +@set LASTCHANGE Fri Apr 17 16:30:16 EDT 2020 @set EDITION 5.0 @set VERSION 5.0 -@set UPDATED 9 April 2020 +@set UPDATED 17 April 2020 @set UPDATED-MONTH April 2020 diff --git a/execute_cmd.c b/execute_cmd.c index 3b40e8066..6e27f5c1b 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -556,7 +556,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, int pipe_in, pipe_out; struct fd_bitmap *fds_to_close; { - int exec_result, user_subshell, invert, ignore_return, was_error_trap; + int exec_result, user_subshell, invert, ignore_return, was_error_trap, fork_flags; REDIRECT *my_undo_list, *exec_undo_list; char *tcmd; volatile int save_line_number; @@ -627,7 +627,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, line_number_for_err_trap = line_number = command->value.Subshell->line; /* XXX - save value? */ /* Otherwise we defer setting line_number */ tcmd = make_command_string (command); - paren_pid = make_child (p = savestring (tcmd), asynchronous); + fork_flags = asynchronous ? FORK_ASYNC : 0; + paren_pid = make_child (p = savestring (tcmd), fork_flags); if (user_subshell && signal_is_trapped (ERROR_TRAP) && signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) @@ -684,7 +685,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, invert = (command->flags & CMD_INVERT_RETURN) != 0; ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - exec_result = wait_for (paren_pid); + exec_result = wait_for (paren_pid, 0); /* If we have to, invert the return value. */ if (invert) @@ -865,7 +866,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, the function to be waited for twice. This also causes subshells forked to execute builtin commands (e.g., in pipelines) to be waited for twice. */ - exec_result = wait_for (last_made_pid); + exec_result = wait_for (last_made_pid, 0); } } @@ -1103,10 +1104,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, last_command_exit_value = exec_result; run_pending_traps (); -#if 0 - if (running_trap == 0) -#endif - currently_executing_command = (COMMAND *)NULL; + currently_executing_command = (COMMAND *)NULL; return (last_command_exit_value); } @@ -2367,7 +2365,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close) BLOCK_SIGNAL (SIGCHLD, set, oset); - coproc_pid = make_child (p = savestring (tcmd), 1); + coproc_pid = make_child (p = savestring (tcmd), FORK_ASYNC); if (coproc_pid == 0) { @@ -2590,12 +2588,12 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) if (INVALID_JOB (lastpipe_jid) == 0) { append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid); - lstdin = wait_for (lastpid); + lstdin = wait_for (lastpid, 0); } else lstdin = wait_for_single_pid (lastpid, 0); /* checks bgpids list */ #else - lstdin = wait_for (lastpid); + lstdin = wait_for (lastpid, 0); #endif #if defined (JOB_CONTROL) @@ -3986,7 +3984,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async) int pipe_in, pipe_out, async; { int r; - int forcefork; + int forcefork, fork_flags; REDIRECT *rd; for (forcefork = 0, rd = redirects; rd; rd = rd->next) @@ -4000,7 +3998,8 @@ execute_null_command (redirects, pipe_in, pipe_out, async) { /* We have a null command, but we really want a subshell to take care of it. Just fork, do piping and redirections, and exit. */ - if (make_child ((char *)NULL, async) == 0) + fork_flags = async ? FORK_ASYNC : 0; + if (make_child ((char *)NULL, fork_flags) == 0) { /* Cancel traps, in trap.c. */ restore_original_signals (); /* XXX */ @@ -4168,6 +4167,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) WORD_LIST *words, *lastword; char *command_line, *lastarg, *temp; int first_word_quoted, result, builtin_is_special, already_forked, dofork; + int fork_flags; pid_t old_last_async_pid; sh_builtin_func_t *builtin; SHELL_VAR *func; @@ -4244,7 +4244,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) /* Don't let a DEBUG trap overwrite the command string to be saved with the process/job associated with this child. */ - if (make_child (p = savestring (the_printed_command_except_trap), async) == 0) + fork_flags = async ? FORK_ASYNC : 0; + if (make_child (p = savestring (the_printed_command_except_trap), fork_flags) == 0) { already_forked = 1; simple_command->flags |= CMD_NO_FORK; @@ -5331,7 +5332,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, int cmdflags; { char *pathname, *command, **args, *p; - int nofork, stdpath, result; + int nofork, stdpath, result, fork_flags; pid_t pid; SHELL_VAR *hookf; WORD_LIST *wl; @@ -5380,7 +5381,10 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE) pid = 0; else - pid = make_child (p = savestring (command_line), async); + { + fork_flags = async ? FORK_ASYNC : 0; + pid = make_child (p = savestring (command_line), fork_flags); + } if (pid == 0) { diff --git a/hashcmd.h b/hashcmd.h index 758f5b4b9..2459f2004 100644 --- a/hashcmd.h +++ b/hashcmd.h @@ -1,6 +1,6 @@ /* hashcmd.h - Common defines for hashing filenames. */ -/* Copyright (C) 1993-2009 Free Software Foundation, Inc. +/* Copyright (C) 1993-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -21,7 +21,7 @@ #include "stdc.h" #include "hashlib.h" -#define FILENAME_HASH_BUCKETS 64 /* must be power of two */ +#define FILENAME_HASH_BUCKETS 256 /* must be power of two */ extern HASH_TABLE *hashed_filenames; @@ -35,9 +35,9 @@ typedef struct _pathdata { #define pathdata(x) ((PATH_DATA *)(x)->data) -extern void phash_create __P((void)); -extern void phash_flush __P((void)); +extern void phash_create PARAMS((void)); +extern void phash_flush PARAMS((void)); -extern void phash_insert __P((char *, char *, int, int)); -extern int phash_remove __P((const char *)); -extern char *phash_search __P((const char *)); +extern void phash_insert PARAMS((char *, char *, int, int)); +extern int phash_remove PARAMS((const char *)); +extern char *phash_search PARAMS((const char *)); diff --git a/jobs.c b/jobs.c index 95e68efce..b791900de 100644 --- a/jobs.c +++ b/jobs.c @@ -1079,7 +1079,7 @@ procsub_waitpid (pid) return -1; if (p->running == PS_DONE) return (p->status); - r = wait_for (p->pid); + r = wait_for (p->pid, 0); return (r); /* defer removing until later */ } @@ -1093,7 +1093,7 @@ procsub_waitall () { if (p->running == PS_DONE) continue; - r = wait_for (p->pid); + r = wait_for (p->pid, 0); } } @@ -2252,7 +2252,7 @@ make_child (command, flags) In this case, we don't want to give the terminal to the shell's process group (we could be in the middle of a pipeline, for example). */ - if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&(SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0) && running_in_background == 0) + if ((flags & FORK_NOTERM) == 0 && async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&(SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0) && running_in_background == 0) give_terminal_to (pipeline_pgrp, 0); #if defined (PGRP_PIPE) @@ -2609,7 +2609,7 @@ wait_for_single_pid (pid, flags) alive = 0; do { - r = wait_for (pid); + r = wait_for (pid, 0); if ((flags & JWAIT_FORCE) == 0) break; @@ -2899,8 +2899,9 @@ job_exit_signal (job) the jobs table. Returns -1 if waitchld() returns -1, indicating that there are no unwaited-for child processes. */ int -wait_for (pid) +wait_for (pid, flags) pid_t pid; + int flags; { int job, termination_state, r; WAIT s; @@ -3235,7 +3236,7 @@ wait_for_job (job, flags, ps) do { - r = wait_for (pid); + r = wait_for (pid, 0); if (r == -1 && errno == ECHILD) mark_all_jobs_as_dead (); @@ -3331,7 +3332,7 @@ return_job: CHECK_WAIT_INTR; errno = 0; - r = wait_for (ANY_PID); /* special sentinel value for wait_for */ + r = wait_for (ANY_PID, 0); /* special sentinel value for wait_for */ if (r == -1 && errno == ECHILD) mark_all_jobs_as_dead (); @@ -3642,7 +3643,7 @@ start_job (job, foreground) pid = find_last_pid (job, 0); UNBLOCK_CHILD (oset); - st = wait_for (pid); + st = wait_for (pid, 0); shell_tty_info = save_stty; set_tty_state (); return (st); diff --git a/jobs.h b/jobs.h index f89669a5e..43ba8c23b 100644 --- a/jobs.h +++ b/jobs.h @@ -38,11 +38,14 @@ /* I looked it up. For pretty_print_job (). The real answer is 24. */ #define LONGEST_SIGNAL_DESC 24 -/* Defines for the wait_for functions and for the wait builtin to use */ -#define JWAIT_PERROR 0x01 -#define JWAIT_FORCE 0x02 -#define JWAIT_NOWAIT 0x04 /* don't waitpid(), just return status if already exited */ -#define JWAIT_WAITING 0x08 /* wait for jobs marked J_WAITING only */ +/* Defines for the wait_for_* functions and for the wait builtin to use */ +#define JWAIT_PERROR (1 << 0) +#define JWAIT_FORCE (1 << 1) +#define JWAIT_NOWAIT (1 << 2) /* don't waitpid(), just return status if already exited */ +#define JWAIT_WAITING (1 << 3) /* wait for jobs marked J_WAITING only */ + +/* flags for wait_for */ +#define JWAIT_NOTERM (1 << 8) /* wait_for doesn't give terminal away */ /* The max time to sleep while retrying fork() on EAGAIN failure */ #define FORKSLEEP_MAX 16 @@ -197,9 +200,10 @@ struct procchain { #define ANY_PID (pid_t)-1 /* flags for make_child () */ -#define FORK_SYNC 0 -#define FORK_ASYNC 1 -#define FORK_NOJOB 2 +#define FORK_SYNC 0 /* normal synchronous process */ +#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 */ /* System calls. */ #if !defined (HAVE_UNISTD_H) @@ -276,7 +280,7 @@ extern int job_exit_signal PARAMS((int)); extern int wait_for_single_pid PARAMS((pid_t, int)); extern void wait_for_background_pids PARAMS((struct procstat *)); -extern int wait_for PARAMS((pid_t)); +extern int wait_for PARAMS((pid_t, int)); extern int wait_for_job PARAMS((int, int, struct procstat *)); extern int wait_for_any_job PARAMS((int, struct procstat *)); diff --git a/nojobs.c b/nojobs.c index b7b64d171..89c09b3d4 100644 --- a/nojobs.c +++ b/nojobs.c @@ -823,8 +823,9 @@ j_strsignal (s) /* Wait for pid (one of our children) to terminate. This is called only by the execution code in execute_cmd.c. */ int -wait_for (pid) +wait_for (pid, flags) pid_t pid; + int flags; { int return_val, pstatus; pid_t got_pid; diff --git a/subst.c b/subst.c index 1ffd618ca..1d91dd5d0 100644 --- a/subst.c +++ b/subst.c @@ -5555,7 +5555,7 @@ wait_procsubs () { if (fifo_list[i].proc != (pid_t)-1 && fifo_list[i].proc > 0) { - r = wait_for (fifo_list[i].proc); + r = wait_for (fifo_list[i].proc, 0); save_proc_status (fifo_list[i].proc, r); fifo_list[i].proc = (pid_t)-1; } @@ -5793,7 +5793,7 @@ wait_procsubs () { if (dev_fd_list[i] != (pid_t)-1 && dev_fd_list[i] > 0) { - r = wait_for (dev_fd_list[i]); + r = wait_for (dev_fd_list[i], 0); save_proc_status (dev_fd_list[i], r); dev_fd_list[i] = (pid_t)-1; } @@ -5901,7 +5901,7 @@ process_substitute (string, open_for_read_in_child) save_pipeline (1); #endif /* JOB_CONTROL */ - pid = make_child ((char *)NULL, 1); + pid = make_child ((char *)NULL, FORK_ASYNC); if (pid == 0) { interactive = 0; @@ -6141,8 +6141,7 @@ read_comsub (fd, quoted, flags, rflag) mb_cur_max = MB_CUR_MAX; nullbyte = 0; - /* Read the output of the command through the pipe. This may need to be - changed to understand multibyte characters in the future. */ + /* Read the output of the command through the pipe. */ while (1) { if (fd < 0) @@ -6206,16 +6205,6 @@ read_comsub (fd, quoted, flags, rflag) #endif istring[istring_index++] = c; - -#if 0 -#if defined (__CYGWIN__) - if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r') - { - istring_index--; - istring[istring_index - 1] = '\n'; - } -#endif -#endif } if (istring) @@ -6267,8 +6256,9 @@ command_substitute (string, quoted, flags) { pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid; char *istring, *s; - int result, fildes[2], function_value, pflags, rc, tflag; + int result, fildes[2], function_value, pflags, rc, tflag, fork_flags; WORD_DESC *ret; + sigset_t set, oset; istring = (char *)NULL; @@ -6323,7 +6313,8 @@ command_substitute (string, quoted, flags) #endif /* JOB_CONTROL */ old_async_pid = last_asynchronous_pid; - pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC); + fork_flags = (subshell_environment&SUBSHELL_ASYNC) ? FORK_ASYNC : 0; + pid = make_child ((char *)NULL, fork_flags); last_asynchronous_pid = old_async_pid; if (pid == 0) @@ -6486,14 +6477,19 @@ command_substitute (string, quoted, flags) dummyfd = fildes[0]; add_unwind_protect (close, dummyfd); + /* Block SIGINT while we're reading from the pipe. If the child + process gets a SIGINT, it will either handle it or die, and the + read will return. */ + BLOCK_SIGNAL (SIGINT, set, oset); tflag = 0; istring = read_comsub (fildes[0], quoted, flags, &tflag); close (fildes[0]); discard_unwind_frame ("read-comsub"); + UNBLOCK_SIGNAL (oset); current_command_subst_pid = pid; - last_command_exit_value = wait_for (pid); + last_command_exit_value = wait_for (pid, 0); last_command_subst_pid = pid; last_made_pid = old_pid; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b0638107..c8bef8dd1 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/appendop.right b/tests/appendop.right index dcb60b0b5..f72696b17 100644 --- a/tests/appendop.right +++ b/tests/appendop.right @@ -17,8 +17,8 @@ 16 ./appendop.tests: line 97: x: readonly variable declare -A foo=([two]="baz" [three]="quux" [one]="bar" ) -declare -A foo=([two]="baz" [0]="zero" [three]="quux" [one]="bar" ) -declare -A foo=([two]="baz" [0]="zero" [three]="quux" [four]="four" [one]="bar" ) +declare -A foo=([0]="zero" [two]="baz" [three]="quux" [one]="bar" ) +declare -A foo=([four]="four" [0]="zero" [two]="baz" [three]="quux" [one]="bar" ) declare -ai iarr=([0]="3" [1]="2" [2]="3") declare -ai iarr=([0]="3" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6") 25 25 diff --git a/tests/array.right b/tests/array.right index afc03bc86..c46ffb5eb 100644 --- a/tests/array.right +++ b/tests/array.right @@ -349,10 +349,10 @@ version[agent] version.agent version[agent] version.agent -version[agent] foo[bar] -version.agent bowl -foo foobar] foo[bar] -bbb bleh bleh +foo[bar] version[agent] +bowl version.agent +foobar] foo foo[bar] +bleh bbb bleh ab] bar 1 diff --git a/tests/assoc.right b/tests/assoc.right index 200362543..e1e45fcbc 100644 --- a/tests/assoc.right +++ b/tests/assoc.right @@ -6,14 +6,14 @@ declare -A BASH_CMDS=() declare -A fluff=([foo]="one" [bar]="two" ) declare -A fluff=([foo]="one" [bar]="two" ) declare -A fluff=([bar]="two" ) -declare -A fluff=([bar]="newval" [qux]="assigned" ) +declare -A fluff=([qux]="assigned" [bar]="newval" ) ./assoc.tests: line 39: chaff: four: must use subscript when assigning associative array declare -A BASH_ALIASES=() declare -A BASH_CMDS=() -declare -Ai chaff=([zero]="5" [one]="10" ) -declare -Ar waste=([lineno]="41" [source]="./assoc.tests" [version]="4.0-devel" [pid]="42134" ) -declare -A wheat=([two]="b" [three]="c" [zero]="0" [one]="a" ) -declare -A chaff=(["hello world"]="flip" [zero]="5" [one]="10" ) +declare -Ai chaff=([one]="10" [zero]="5" ) +declare -Ar waste=([pid]="42134" [lineno]="41" [source]="./assoc.tests" [version]="4.0-devel" ) +declare -A wheat=([two]="b" [three]="c" [one]="a" [zero]="0" ) +declare -A chaff=(["hello world"]="flip" [one]="10" [zero]="5" ) ./assoc.tests: line 51: waste: readonly variable ./assoc.tests: line 52: unset: waste: cannot unset: readonly variable ./assoc.tests: line 53: chaff[*]: bad array subscript @@ -35,11 +35,11 @@ argv[1] = ./assoc.tests: line 71: declare: chaff: cannot destroy array variables in this way ./assoc.tests: line 73: chaff[*]: bad array subscript ./assoc.tests: line 74: [*]=12: invalid associative array key -declare -A wheat=(["foo bar"]="qux qix" [six]="6" ) +declare -A wheat=([six]="6" ["foo bar"]="qux qix" ) argv[1] = argv[2] = argv[1] = -declare -A wheat=(["foo bar"]="qux qix" [six]="6" ) +declare -A wheat=([six]="6" ["foo bar"]="qux qix" ) argv[1] = <2> argv[1] = <7> argv[1] = @@ -48,16 +48,16 @@ argv[3] = argv[1] = argv[1] = <16> argv[1] = <16> -argv[1] = -argv[2] = <6> -argv[1] = -argv[2] = -argv[3] = -argv[1] = -argv[2] = +argv[1] = <6> +argv[2] = +argv[1] = +argv[2] = +argv[3] = +argv[1] = +argv[2] = 8 -/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin -sbin bin bin ucb bin . sbin bin +/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin +bin bin . bin ucb sbin bin sbin bin / / / / / / / / @@ -66,27 +66,27 @@ argv[1] = argv[1] = argv[1] = 8 -/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin -sbin bin bin ucb bin . sbin bin +/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin +bin bin . bin ucb sbin bin sbin / / / / / / / 8 4 -- /bin -^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin -^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin -\sbin \usr/bin \bin \usr/ucb \usr/local/bin . \usr/sbin \bin -\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin -\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin +^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin +^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin +\usr/local/bin \bin . \usr/bin \usr/ucb \usr/sbin \bin \sbin +\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin +\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin ([a]=1) foo qux /usr/sbin/foo /usr/local/bin/qux hits command - 0 /sbin/blat 0 /usr/sbin/foo 0 /bin/sh + 0 /sbin/blat 0 /usr/local/bin/qux -blat foo sh qux -/sbin/blat /usr/sbin/foo /bin/sh /usr/local/bin/qux +foo sh blat qux +/usr/sbin/foo /bin/sh /sbin/blat /usr/local/bin/qux foo qux argv[1] = @@ -104,10 +104,10 @@ argv[4] = outside: outside declare -A BASH_ALIASES=() declare -A BASH_CMDS=() -declare -A afoo=(["foo bar"]="foo quux" [six]="six" ) +declare -A afoo=([six]="six" ["foo bar"]="foo quux" ) argv[1] = -argv[2] = -argv[3] = +argv[2] = +argv[3] = outside 2: outside argv[1] = argv[1] = <> @@ -138,11 +138,11 @@ abc def def ./assoc5.sub: line 26: declare: `myarray[foo[bar]=bleh': not a valid identifier -bleh def abc -myarray=([foo]="bleh" ["]"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" ) +def bleh abc +myarray=(["]"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" ) 123 -myarray=([foo]="bleh" ["]"]="def" ["a]=test2;#a"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" ) +myarray=(["]"]="def" ["a]=test2;#a"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" ) bar"bie doll declare -A foo=(["bar\"bie"]="doll" ) @@ -234,11 +234,11 @@ main: declare -- a="42" declare -A a=([3]="" [1]="2" ) declare -A foo=([d]="4" [c]="3" [b]="2" [a]="1" ) foo=( d "4" c "3" b "2" a "1" ) -declare -A foo=(["spa ces"]="2" ["\\"]="5" ["@"]="3" ["holy hell this works"]="4" ["a b"]="1" ) -foo=( echo "spa ces" "2" "\\" "5" "@" "3" "holy hell this works" "4" "a b" "1" ) +declare -A foo=(["\\"]="5" ["@"]="3" ["holy hell this works"]="4" ["a b"]="1" ["spa ces"]="2" ) +foo=( echo "\\" "5" "@" "3" "holy hell this works" "4" "a b" "1" "spa ces" "2" ) ./assoc11.sub: line 34: "": bad array subscript -declare -A foo=(["foo[bar"]="bleh" [";"]="semicolon" ["]"]="def" [a=b]="assignment" ["a]a"]="abc" ) -foo=( "foo[bar" "bleh" ";" "semicolon" "]" "def" a=b "assignment" "a]a" "abc" ) +declare -A foo=([";"]="semicolon" ["]"]="def" [a=b]="assignment" ["a]a"]="abc" ["foo[bar"]="bleh" ) +foo=( ";" "semicolon" "]" "def" a=b "assignment" "a]a" "abc" "foo[bar" "bleh" ) declare -A foo=(["'"]="squote" ["\""]="dquote" ["\\"]="bslash" ["\`"]="backquote" ) foo=( "'" "squote" "\"" "dquote" "\\" "bslash" "\`" "backquote" ) declare -A foo=(["bar]bie"]="doll" ["a]=test1;#a"]="123" ["bar\"bie"]="doll" ) diff --git a/tests/new-exp.right b/tests/new-exp.right index 2a1e05d95..307a91859 100644 --- a/tests/new-exp.right +++ b/tests/new-exp.right @@ -635,7 +635,7 @@ declare -r x='ab '\''cd'\'' ef' set -- 'ab' 'cd ef' '' 'gh' declare -a A=([0]="ab" [1]="cd ef" [2]="" [3]="gh") declare -a B=() -declare -A A=([two]="b c" [three]="" [four]="de" [one]="1" ) +declare -A A=([four]="de" [two]="b c" [three]="" [one]="1" ) r a A diff --git a/tests/type.right b/tests/type.right index 76ce22953..f876715a0 100644 --- a/tests/type.right +++ b/tests/type.right @@ -44,8 +44,8 @@ builtin is a shell builtin bash is hashed (/tmp/bash) file hits command - 3 /tmp/bash 1 /bin/sh + 3 /tmp/bash f is a function f () { diff --git a/tests/varenv.right b/tests/varenv.right index 4c8ef2204..b16b4033f 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -133,7 +133,7 @@ after func: x = outside ./varenv11.sub: line 18: qux: readonly variable declare -A foo=([zero]="zero" [one]="one" ) declare -a bar=([0]="zero" [1]="one") -declare -A foo=([zero]="zero" [one]="one" ) +declare -A foo=([one]="one" [zero]="zero" ) declare -a bar=([0]="zero" [1]="one") ./varenv11.sub: line 42: a: readonly variable foo=abc diff --git a/variables.c b/variables.c index aacc12fa4..b06b606f5 100644 --- a/variables.c +++ b/variables.c @@ -3015,7 +3015,7 @@ make_new_assoc_variable (name) HASH_TABLE *hash; entry = make_new_variable (name, global_variables->table); - hash = assoc_create (0); + hash = assoc_create (ASSOC_HASH_BUCKETS); var_setassoc (entry, hash); VSETATTR (entry, att_assoc); @@ -3047,7 +3047,7 @@ make_local_assoc_variable (name, flags) internal_warning ("%s: cannot inherit value from incompatible type", name); VUNSETATTR (var, att_array); dispose_variable_value (var); - hash = assoc_create (0); + hash = assoc_create (ASSOC_HASH_BUCKETS); var_setassoc (var, hash); } else if (localvar_inherit) @@ -3055,7 +3055,7 @@ make_local_assoc_variable (name, flags) else { dispose_variable_value (var); - hash = assoc_create (0); + hash = assoc_create (ASSOC_HASH_BUCKETS); var_setassoc (var, hash); } -- 2.47.2