From cf58e12ce6437c2a4e8ffc704cdcb53e9912f077 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Fri, 20 Mar 2020 09:26:56 -0400 Subject: [PATCH] commit bash-20200316 snapshot --- CWRU/CWRU.chlog | 62 ++++++++++++++++++++++++++++++++++- builtins/declare.def | 23 ++++++++----- doc/bash.1 | 15 ++++++--- doc/bashref.texi | 8 ++++- doc/version.texi | 6 ++-- examples/loadables/accept.c | 2 +- examples/loadables/basename.c | 11 +++---- examples/loadables/strftime.c | 8 +++-- execute_cmd.c | 3 +- jobs.c | 5 --- lib/readline/bind.c | 7 ++++ lib/readline/histfile.c | 22 +++++++++---- subst.c | 13 +++++--- subst.h | 1 + tests/RUN-ONE-TEST | 2 +- tests/RUN-ONE-TEST.verb | 13 ++++++++ tests/jobs.right | 34 ++++++++++--------- tests/jobs.tests | 37 +++++++++++---------- tests/shopt.right | 2 ++ tests/shopt.tests | 4 +++ variables.c | 20 ++++++----- variables.h | 6 ++-- 22 files changed, 214 insertions(+), 90 deletions(-) create mode 100755 tests/RUN-ONE-TEST.verb diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index ec0d9f41..7c664727 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -7339,7 +7339,7 @@ expr.c test.c - unary_test: allow -v N to test whether or not positional parameter N is set. Most recently suggested by Peng Yu - and Martijn Dekker + and Martijn Dekker builtins/getopts.def - dogetopts: use number_of_args() to compute the number of positional @@ -7540,3 +7540,63 @@ subst.c we are returning a quoted null string to the caller by setting W_HASQUOTEDNULL. Fixes bug reported by Martin Castillo + + 3/17 + ---- +lib/readline/histfile.c + - history_truncate_file: only chown the file if we really need to. From + alex@lisas.de via https://savannah.gnu.org/support/?110207 + +lib/readline/bind.c + - rl_unbind_function_in_map: since we are looking for functions, not + key sequences, descend into keymaps attached to the keymap passed + as an argument. From a report from lockywolf@gmail.com back on 2/27, + TENTATIVE CHANGE + +variables.h + - MKLOC_ARRAYOK,MKLOC_ASSOCOK: new flags values for + make_local_{array,assoc}_variable so we can avoid hard-coded values + of 1 and make it possible to eventually pass in additional flags + +builtins/declare.def + - declare_internal: make_local_array_variable: pass MKLOC_ASSOCOK + - declare_internal: make_local_assoc_variable: pass MKLOC_ARRAYOK + +variables.c + - make_local_{array,assoc}_variable: understand new flags, pass + MKLOC_INHERIT to make_local_variable if it appears in the flags + argument + +builtins/declare.def + - declare_internal: add a new -I option for local and declare that + inherits attributes and value from a variable with the same name + at a previous scope. Inspired by netbsd sh + - if -I option is supplied, pass MKLOC_INHERIT to make_local_variable + and its array counterparts make_local_{array,assoc}_variable + +subst.c + - shell_expand_word_list: pass -I to declare if constructing a declare + command with make_local_declare, meaning we have an array or assoc + compound assignment. (Slighty unsatisfactory, but ok for now) Fix + for bug report from Kevin Locke , + https://savannah.gnu.org/support/index.php?109669 + + 3/18 + ---- +examples/loadables/basename.c + - basename_builtin: handle -- option without crashing. Report by Peng Yu + + +jobs.c + - notify_of_job_status: if in posix-mode shell is started with -c, + jobs should print the status of completed jobs. From a report by + Robert Elz back in 12/18 + + 3/19 + ---- +variables.c + - assign_in_env: if we're assigning POSIXLY_CORRECT or POSIX_PEDANTIC + in the temporary environment, save the values of the options + affected by posix mode so we can restore them when we restore the + old value of the variable after the command executes. Suggested by + Martijn Dekker diff --git a/builtins/declare.def b/builtins/declare.def index b1b69274..7af62c39 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -34,6 +34,8 @@ Options: source file when debugging) -g create global variables when used in a shell function; otherwise ignored + -I if creating a local variable, inherit the attributes and value + of a variable with the same name at a previous scope -p display the attributes and value of each NAME Options which set attributes: @@ -135,9 +137,9 @@ local_builtin (list) } #if defined (ARRAY_VARS) -# define DECLARE_OPTS "+acfgilnprtuxAFG" +# define DECLARE_OPTS "+acfgilnprtuxAFGI" #else -# define DECLARE_OPTS "+cfgilnprtuxFG" +# define DECLARE_OPTS "+cfgilnprtuxFGI" #endif static SHELL_VAR * @@ -168,13 +170,13 @@ declare_internal (list, local_var) { int flags_on, flags_off, *flags; int any_failed, assign_error, pflag, nodefs, opt, onref, offref; - int mkglobal, chklocal; + int mkglobal, chklocal, inherit_flag; char *t, *subscript_start; SHELL_VAR *var, *refvar, *v; FUNCTION_DEF *shell_fn; flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0; - mkglobal = chklocal = 0; + mkglobal = chklocal = inherit_flag = 0; refvar = (SHELL_VAR *)NULL; reset_internal_getopt (); while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1) @@ -255,6 +257,9 @@ declare_internal (list, local_var) flags_off |= att_capcase|att_lowercase; break; #endif /* CASEMOD_ATTRS */ + case 'I': + inherit_flag = MKLOC_INHERIT; + break; CASE_HELPOPT; default: builtin_usage (); @@ -452,9 +457,9 @@ restart_new_var_name: return an existing {array,assoc} variable to be flagged as an error below. */ if (flags_on & att_assoc) - var = make_local_assoc_variable (newname, 1); + var = make_local_assoc_variable (newname, MKLOC_ARRAYOK|inherit_flag); else if ((flags_on & att_array) || making_array_special) - var = make_local_array_variable (newname, 1); + var = make_local_array_variable (newname, MKLOC_ASSOCOK|inherit_flag); else #endif if (offset == 0 && (flags_on & att_nameref)) @@ -468,18 +473,18 @@ restart_new_var_name: if (refvar && refvar->context != variable_context) { refvar = 0; - var = make_local_variable (name, 0); + var = make_local_variable (name, inherit_flag); } else if (refvar && refvar->context == variable_context) var = refvar; /* Maybe we just want to create a new local variable */ else if (var == 0 || var->context != variable_context) - var = make_local_variable (name, 0); + var = make_local_variable (name, inherit_flag); /* otherwise we have a var at the right context */ } else /* XXX - check name for validity here with valid_nameref_value */ - var = make_local_variable ((flags_on & att_nameref) ? name : newname, 0); /* sets att_invisible for new vars */ + var = make_local_variable ((flags_on & att_nameref) ? name : newname, inherit_flag); /* sets att_invisible for new vars */ if (var == 0) { diff --git a/doc/bash.1 b/doc/bash.1 index 86e725d7..be184d3c 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Wed Jan 29 14:00:16 EST 2020 +.\" Last Change: Tue Mar 17 18:27:36 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 January 29" "GNU Bash 5.0" +.TH BASH 1 "2020 March 17" "GNU Bash 5.0" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -8023,10 +8023,10 @@ is greater than the number of enclosing loops, the last enclosing loop (the ``top-level'' loop) is resumed. The return value is 0 unless \fIn\fP is not greater than or equal to 1. .TP -\fBdeclare\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] +\fBdeclare\fP [\fB\-aAfFgiIlnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] .PD 0 .TP -\fBtypeset\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] +\fBtypeset\fP [\fB\-aAfFgiIlnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] .PD Declare variables and/or give them attributes. If no \fIname\fPs are given then display the values of variables. @@ -8061,6 +8061,13 @@ The option forces variables to be created or modified at the global scope, even when \fBdeclare\fP is executed in a shell function. It is ignored in all other cases. +The +.B \-I +option causes local variables to inherit the attributes +(except the \fInameref\fP attribute) +and value of any existing variable with the same +\fIname\fP at a surrounding scope. +If there is no existing variable, the local variable is initially unset. The following options can be used to restrict output to variables with the specified attribute or to give variables attributes: diff --git a/doc/bashref.texi b/doc/bashref.texi index 8cfb7759..b4083e1d 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4142,7 +4142,7 @@ zero if @var{command} is found, and non-zero if not. @item declare @btindex declare @example -declare [-aAfFgilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] +declare [-aAfFgiIlnrtux] [-p] [@var{name}[=@var{value}] @dots{}] @end example Declare variables and give them attributes. If no @var{name}s @@ -4171,6 +4171,12 @@ The @option{-g} option forces variables to be created or modified at the global scope, even when @code{declare} is executed in a shell function. It is ignored in all other cases. +The @option{-I} option causes local variables to inherit the attributes +(except the @var{nameref} attribute) +and value of any existing variable with the same +@var{name} at a surrounding scope. +If there is no existing variable, the local variable is initially unset. + The following options can be used to restrict output to variables with the specified attributes or to give variables attributes: diff --git a/doc/version.texi b/doc/version.texi index 450eef77..411233df 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 Wed Jan 29 13:59:06 EST 2020 +@set LASTCHANGE Tue Mar 17 18:27:12 EDT 2020 @set EDITION 5.0 @set VERSION 5.0 -@set UPDATED 29 January 2020 -@set UPDATED-MONTH January 2020 +@set UPDATED 17 March 2020 +@set UPDATED-MONTH March 2020 diff --git a/examples/loadables/accept.c b/examples/loadables/accept.c index b1af5042..54cf38c8 100644 --- a/examples/loadables/accept.c +++ b/examples/loadables/accept.c @@ -85,7 +85,7 @@ accept_builtin (list) if (tmoutarg) { long ival, uval; - opt = uconvert (tmoutarg, &ival, &uval); + opt = uconvert (tmoutarg, &ival, &uval, (char **)0); if (opt == 0 || ival < 0 || uval < 0) { builtin_error ("%s: invalid timeout specification", tmoutarg); diff --git a/examples/loadables/basename.c b/examples/loadables/basename.c index 0734322d..29dd1a6d 100644 --- a/examples/loadables/basename.c +++ b/examples/loadables/basename.c @@ -3,7 +3,7 @@ /* See Makefile for compilation details. */ /* - Copyright (C) 1999-2009 Free Software Foundation, Inc. + Copyright (C) 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash. Bash is free software: you can redistribute it and/or modify @@ -39,15 +39,14 @@ basename_builtin (list) int slen, sufflen, off; char *string, *suffix, *fn; + if (no_options (list)) + return (EX_USAGE); + list = loptend; if (list == 0) { builtin_usage (); return (EX_USAGE); - } - - if (no_options (list)) - return (EX_USAGE); - list = loptend; + } string = list->word->word; suffix = (char *)NULL; diff --git a/examples/loadables/strftime.c b/examples/loadables/strftime.c index a6190f1c..f4e194e6 100644 --- a/examples/loadables/strftime.c +++ b/examples/loadables/strftime.c @@ -34,6 +34,7 @@ #include "builtins.h" #include "shell.h" #include "common.h" +#include "bashgetopt.h" int strftime_builtin (list) @@ -46,15 +47,16 @@ strftime_builtin (list) int n; intmax_t i; + if (no_options (list)) + return (EX_USAGE); + list = loptend; + if (list == 0) { builtin_usage (); return (EX_USAGE); } - if (no_options (list)) - return (EX_USAGE); - format = list->word->word; if (format == 0 || *format == 0) { diff --git a/execute_cmd.c b/execute_cmd.c index 56edd006..407528bb 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1606,8 +1606,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) if (should_redir_stdin && stdin_redir == 0) async_redirect_stdin (); -#if 0 - /* XXX - TAG:bash-5.1 */ +#if 0 /* XXX - TAG:bash-5.1 */ if (user_subshell && command->type == cm_subshell) optimize_subshell_command (command->value.Subshell->command); #endif diff --git a/jobs.c b/jobs.c index e157c38f..8f5449ac 100644 --- a/jobs.c +++ b/jobs.c @@ -4265,14 +4265,9 @@ notify_of_job_status () substitution, so don't print anything. Otherwise, if the shell is not interactive, POSIX says that `jobs' is the only way to notify of job status. */ -#if 1 - if ((job_control == 0 && interactive_shell) || - (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB))) -#else /* TAG:bash-5.1 */ if ((job_control == 0 && interactive_shell) || (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)) || (startup_state == 2 && posixly_correct && (subshell_environment & SUBSHELL_COMSUB) == 0)) -#endif { /* POSIX.2 compatibility: if the shell is not interactive, hang onto the job corresponding to the last asynchronous diff --git a/lib/readline/bind.c b/lib/readline/bind.c index 9eb484d9..3cbed2cc 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -262,6 +262,13 @@ rl_unbind_function_in_map (rl_command_func_t *func, Keymap map) map[i].function = (rl_command_func_t *)NULL; rval = 1; } + else if (map[i].type == ISKMAP) /* TAG:readline-8.1 */ + { + int r; + r = rl_unbind_function_in_map (func, FUNCTION_TO_KEYMAP (map, i)); + if (r == 1) + rval = 1; + } } return rval; } diff --git a/lib/readline/histfile.c b/lib/readline/histfile.c index a38d3952..f0fa5ce1 100644 --- a/lib/readline/histfile.c +++ b/lib/readline/histfile.c @@ -507,6 +507,12 @@ histfile_restore (const char *backup, const char *orig) return (history_rename (backup, orig)); } +/* Should we call chown, based on whether finfo and nfinfo describe different + files with different owners? */ + +#define SHOULD_CHOWN(finfo, nfinfo) \ + (finfo.st_uid != nfinfo.st_uid || finfo.st_gid != nfinfo.st_gid) + /* Truncate the history file FNAME, leaving only LINES trailing lines. If FNAME is NULL, then use ~/.history. Writes a new file and renames it to the original name. Returns 0 on success, errno on failure. */ @@ -515,7 +521,7 @@ history_truncate_file (const char *fname, int lines) { char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */ int file, chars_read, rv, orig_lines, exists, r; - struct stat finfo; + struct stat finfo, nfinfo; size_t file_size; history_lines_written_to_file = 0; @@ -536,6 +542,9 @@ history_truncate_file (const char *fname, int lines) } exists = 1; + nfinfo.st_uid = finfo.st_uid; + nfinfo.st_gid = finfo.st_gid; + if (S_ISREG (finfo.st_mode) == 0) { close (file); @@ -624,6 +633,9 @@ history_truncate_file (const char *fname, int lines) if (write (file, bp, chars_read - (bp - buffer)) < 0) rv = errno; + if (fstat (file, &nfinfo) < 0 && rv == 0) + rv = errno; + if (close (file) < 0 && rv == 0) rv = errno; } @@ -651,7 +663,7 @@ history_truncate_file (const char *fname, int lines) user is running this, it's a no-op. If the shell is running after sudo with a shared history file, we don't want to leave the history file owned by root. */ - if (rv == 0 && exists) + if (rv == 0 && exists && SHOULD_CHOWN (finfo, nfinfo)) r = chown (filename, finfo.st_uid, finfo.st_gid); #endif @@ -670,7 +682,7 @@ history_do_write (const char *filename, int nelements, int overwrite) register int i; char *output, *tempname, *histname; int file, mode, rv, exists; - struct stat finfo; + struct stat finfo, nfinfo; #ifdef HISTORY_USE_MMAP size_t cursize; @@ -715,15 +727,11 @@ history_do_write (const char *filename, int nelements, int overwrite) the_history = history_list (); /* Calculate the total number of bytes to write. */ for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) -#if 0 - buffer_size += 2 + HISTENT_BYTES (the_history[i]); -#else { if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) buffer_size += strlen (the_history[i]->timestamp) + 1; buffer_size += strlen (the_history[i]->line) + 1; } -#endif /* Allocate the buffer, and fill it. */ #ifdef HISTORY_USE_MMAP diff --git a/subst.c b/subst.c index 7b91a48f..88570fd7 100644 --- a/subst.c +++ b/subst.c @@ -7448,8 +7448,7 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p) from end of positional parameters? */ #if 1 if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0) -#else - /* XXX - TAG: bash-5.1 */ +#else /* XXX - TAG: bash-5.1 */ if (vtype == VT_ARRAYVAR && *e2p < 0) #endif { @@ -11517,14 +11516,20 @@ shell_expand_word_list (tlist, eflags) opts[opti++] = 'A'; } else if (tlist->word->flags & W_ASSIGNASSOC) - opts[opti++] = 'A'; + { + opts[opti++] = 'A'; + opts[opti++] = 'I'; + } else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL)) { opts[opti++] = 'g'; opts[opti++] = 'a'; } else if (tlist->word->flags & W_ASSIGNARRAY) - opts[opti++] = 'a'; + { + opts[opti++] = 'a'; + opts[opti++] = 'I'; + } else if (tlist->word->flags & W_ASSNGLOBAL) opts[opti++] = 'g'; diff --git a/subst.h b/subst.h index 7a18b18d..c3ad2661 100644 --- a/subst.h +++ b/subst.h @@ -54,6 +54,7 @@ #define ASS_NOEXPAND 0x0080 /* don't expand associative array subscripts */ #define ASS_NOEVAL 0x0100 /* don't evaluate value as expression */ #define ASS_NOLONGJMP 0x0200 /* don't longjmp on fatal assignment error */ +#define ASS_NOINVIS 0x0400 /* don't resolve local invisible variables */ /* Flags for the string extraction functions. */ #define SX_NOALLOC 0x0001 /* just skip; don't return substring */ diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b063810..c8bef8dd 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/RUN-ONE-TEST.verb b/tests/RUN-ONE-TEST.verb new file mode 100755 index 00000000..92b78a22 --- /dev/null +++ b/tests/RUN-ONE-TEST.verb @@ -0,0 +1,13 @@ +BUILD_DIR=/usr/local/build/bash/bash-current +THIS_SH="$BUILD_DIR/bash -x" +PATH=$PATH:$BUILD_DIR + +export THIS_SH PATH BUILD_DIR + +: ${TMPDIR:=/tmp} +export TMPDIR + +export BASH_TSTOUT=/tmp/xx +rm -f ${BASH_TSTOUT} + +/bin/sh -x "$@" diff --git a/tests/jobs.right b/tests/jobs.right index 0fe2abec..01b267d2 100644 --- a/tests/jobs.right +++ b/tests/jobs.right @@ -40,33 +40,35 @@ async list wait-for-background-pids async list wait for child forked wait-when-no-children +posix jobs output +[1]+ Done sleep 1 wait-for-job -./jobs.tests: line 79: wait: %2: no such job +./jobs.tests: line 82: wait: %2: no such job 127 async list wait-for-job forked fg-bg 1 -sleep 5 +sleep 2 fg-bg 2 -sleep 5 +sleep 2 fg-bg 3 -sleep 5 +sleep 2 fg-bg 4 -sleep 5 +sleep 2 fg-bg 5 -./jobs.tests: line 106: fg: %2: no such job -./jobs.tests: line 107: bg: job 1 already in background +./jobs.tests: line 109: fg: %2: no such job +./jobs.tests: line 110: bg: job 1 already in background fg-bg 6 -./jobs.tests: line 114: fg: -s: invalid option +./jobs.tests: line 117: fg: -s: invalid option fg: usage: fg [job_spec] -./jobs.tests: line 115: bg: -s: invalid option +./jobs.tests: line 118: bg: -s: invalid option bg: usage: bg [job_spec ...] -./jobs.tests: line 120: disown: -s: invalid option +./jobs.tests: line 123: disown: -s: invalid option disown: usage: disown [-h] [-ar] [jobspec ... | pid ...] -./jobs.tests: line 124: disown: %1: no such job -./jobs.tests: line 127: disown: %2: no such job +./jobs.tests: line 127: disown: %1: no such job +./jobs.tests: line 130: disown: %2: no such job wait-for-non-child -./jobs.tests: line 130: wait: pid 1 is not a child of this shell +./jobs.tests: line 133: wait: pid 1 is not a child of this shell 127 3 -- 1 2 3 -- 1 - 2 - 3 [1] Running sleep 300 & @@ -76,8 +78,8 @@ running jobs: [1] Running sleep 300 & [2]- Running sleep 350 & [3]+ Running sleep 400 & -./jobs.tests: line 147: kill: %4: no such job -./jobs.tests: line 149: jobs: %4: no such job +./jobs.tests: line 150: kill: %4: no such job +./jobs.tests: line 152: jobs: %4: no such job current job: [3]+ Running sleep 400 & previous job: @@ -105,5 +107,5 @@ after kill -STOP, backgrounding %3: killing... done after KILL -STOP, foregrounding %1 -sleep 10 +sleep 4 done diff --git a/tests/jobs.tests b/tests/jobs.tests index ce8f2f09..ae9c4ee8 100644 --- a/tests/jobs.tests +++ b/tests/jobs.tests @@ -49,7 +49,7 @@ wait # make sure we reap the processes while stderr is still redirected exec 2>&5 echo wait-for-pid -sleep 10 & +sleep 4 & wait $! echo wait-errors @@ -57,52 +57,55 @@ wait 1-1 wait -- -4 echo wait-for-background-pids -sleep 5 & -sleep 8 & +sleep 2 & +sleep 4 & wait echo async list wait-for-background-pids -sleep 5 & sleep 8 & +sleep 2 & sleep 4 & wait echo async list wait for child -sleep 5 & echo forked +sleep 2 & echo forked wait echo wait-when-no-children wait +echo posix jobs output +${THIS_SH} -o posix -c 'sleep 1 & P=$! ; sleep 2; jobs; wait' + set -m echo wait-for-job -sleep 5 & +sleep 3 & wait %2 # this should be a no-such-job error echo $? wait %1 echo async list wait-for-job -sleep 5 & echo forked +sleep 2 & echo forked wait %1 echo fg-bg 1 -sleep 5 & +sleep 2 & %1 echo fg-bg 2 -sleep 5 & +sleep 2 & fg %% echo fg-bg 3 -sleep 5 & +sleep 2 & fg %s echo fg-bg 4 -sleep 5 & +sleep 2 & fg %?ee # these next two are error cases echo fg-bg 5 -sleep 15 & +sleep 2 & fg %2 # this should be a no-such-job error bg %1 # this should be a `bg background job?' error wait @@ -110,7 +113,7 @@ wait # these may someday mean to start the jobs, but not print the line # describing the status, but for now they are errors echo fg-bg 6 -sleep 5 & +sleep 2 & fg -s %1 bg -s %1 wait @@ -153,7 +156,7 @@ echo previous job: jobs %- kill -STOP %2 -sleep 5 # give time for the shell to get the stop notification +sleep 3 # give time for the shell to get the stop notification echo after kill -STOP echo running jobs: jobs -r @@ -177,7 +180,7 @@ echo stopped jobs: jobs -s kill -STOP %3 -sleep 5 # give time for the shell to get the stop notification +sleep 3 # give time for the shell to get the stop notification echo after kill -STOP, backgrounding %3: bg %3 @@ -195,9 +198,9 @@ echo done exec 2>&5 -sleep 10 & +sleep 4 & kill -STOP %1 -sleep 5 # give time for the shell to get the stop notification +sleep 2 # give time for the shell to get the stop notification echo after KILL -STOP, foregrounding %1 fg %1 diff --git a/tests/shopt.right b/tests/shopt.right index f1fb1862..8cf46db6 100644 --- a/tests/shopt.right +++ b/tests/shopt.right @@ -294,3 +294,5 @@ xtrace off -- ./shopt.tests: line 106: shopt: xyz1: invalid shell option name ./shopt.tests: line 107: shopt: xyz1: invalid option name +expand_aliases on +expand_aliases on diff --git a/tests/shopt.tests b/tests/shopt.tests index fb765209..c31870cf 100644 --- a/tests/shopt.tests +++ b/tests/shopt.tests @@ -107,3 +107,7 @@ shopt -p xyz1 shopt -o -p xyz1 ${THIS_SH} ./shopt1.sub + +# test whether or not temporary variable assignments that manipulate posix +# mode restore the previous state or the default non-posix state +${THIS_SH} -c 'shopt -s expand_aliases ; shopt expand_aliases ; POSIXLY_CORRECT=y true ; shopt expand_aliases' diff --git a/variables.c b/variables.c index 7a3d2786..e75b8cc7 100644 --- a/variables.c +++ b/variables.c @@ -2951,14 +2951,17 @@ make_new_array_variable (name) } SHELL_VAR * -make_local_array_variable (name, assoc_ok) +make_local_array_variable (name, flags) char *name; - int assoc_ok; + int flags; { SHELL_VAR *var; ARRAY *array; + int assoc_ok; - var = make_local_variable (name, 0); /* XXX for now */ + assoc_ok = flags & MKLOC_ASSOCOK; + + var = make_local_variable (name, flags & MKLOC_INHERIT); /* XXX for now */ /* If ASSOC_OK is non-zero, assume that we are ok with letting an assoc variable return to the caller without converting it. The caller will either flag an error or do the conversion itself. */ @@ -3004,14 +3007,17 @@ make_new_assoc_variable (name) } SHELL_VAR * -make_local_assoc_variable (name, array_ok) +make_local_assoc_variable (name, flags) char *name; - int array_ok; + int flags; { SHELL_VAR *var; HASH_TABLE *hash; + int array_ok; - var = make_local_variable (name, 0); /* XXX for now */ + array_ok = flags & MKLOC_ARRAYOK; + + var = make_local_variable (name, flags & MKLOC_INHERIT); /* XXX for now */ /* If ARRAY_OK is non-zero, assume that we are ok with letting an array variable return to the caller without converting it. The caller will either flag an error or do the conversion itself. */ @@ -3791,10 +3797,8 @@ assign_in_env (word, flags) if (flags) { -#if 0 /* TAG:bash-5.1 from Martijn Dekker */ if (STREQ (newname, "POSIXLY_CORRECT") || STREQ (newname, "POSIX_PEDANDTIC")) save_posix_options (); /* XXX one level of saving right now */ -#endif stupidly_hack_special_variables (newname); } diff --git a/variables.h b/variables.h index a751afe4..3865d21a 100644 --- a/variables.h +++ b/variables.h @@ -221,8 +221,10 @@ typedef struct _vlist { #define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0') -/* Flag values for make_local_variable */ -#define MKLOC_INHERIT 0x01 +/* Flag values for make_local_variable and its array counterparts */ +#define MKLOC_ASSOCOK 0x01 +#define MKLOC_ARRAYOK 0x02 +#define MKLOC_INHERIT 0x04 /* Special value for nameref with invalid value for creation or assignment */ extern SHELL_VAR nameref_invalid_value;