and though bugs are the bane of my existence, rest assured the wretched thing will get the best of care here

You need to sign in or sign up before continuing.
...
 
Commits (2)
......@@ -9260,3 +9260,45 @@ examples/loadables/stat.c
examples/loadables/Makefile.in
- stat: now built and installed by default
12/31
-----
command.h
- SUBSHELL_IGNTRAP: new flag value
jobs.c
- make_child: set SUBSHELL_IGNTRAP in subshell_environment in the
child process, meaning that we should not execute trap handlers for
trapped signals
execute_cmd.c
- execute_in_subshell, execute_simple_command, execute_disk_command:
make sure to unset SUBSHELL_IGNTRAP after a child process restores
the original signal dispositions
- execute_simple_command: make sure to set SUBSHELL_IGNTRAP after
make_child returns and we're setting subshell_environment directly
subst.c
- command_substitute,process_substitute: unset SUBSHELL_IGNTRAP after
the child process has reset the trapped signal dispositions
trap.c
- trap_handler: if we get a signal for which we have set a trap, but
SUBSHELL_IGNTRAP is set in subshell_environmnent, make sure we
restore the original signal disposition and resend the signal to
ourselves. Fixes issue reported by Nikolay Borisov <nborisov@suse.com>
(or at least makes the race window much smaller)
sig.c
- initialize_terminating_signal: set the original signal handler from
the return value from sigaction; a minor optimization that saves a
system call or two
1/5/2021
--------
builtins/declare.def
- declare_internal: make some option combinations that don't make
sense errors (e.g., -f and -a/-A/-i/-n)
- declare_internal: if we build a new variable name by expanding the
value of a nameref variable, make sure to chop the `+' in a `+='
off before going on
......@@ -1214,6 +1214,7 @@ tests/nameref18.sub f
tests/nameref19.sub f
tests/nameref20.sub f
tests/nameref21.sub f
tests/nameref22.sub f
tests/nameref.right f
tests/new-exp.tests f
tests/new-exp1.sub f
......
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
......@@ -306,6 +306,24 @@ declare_internal (list, local_var)
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
}
/* Some option combinations that don't make any sense */
if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
{
char *optchar;
if (flags_on & att_nameref)
optchar = "-n";
else if (flags_on & att_integer)
optchar = "-i";
else if (flags_on & att_assoc)
optchar = "-A";
else if (flags_on & att_array)
optchar = "-a";
sh_invalidopt (optchar);
return (EXECUTION_FAILURE);
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
......@@ -698,8 +716,8 @@ restart_new_var_name:
assign_error++;
NEXT_VARIABLE ();
}
name[offset] = '\0';
value = name + namelen;
name[(aflags & ASS_APPEND) ? offset - 1 : offset] = '\0';
value = name + namelen; /* XXX name + offset + 1? */
}
free (oldname);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -124,6 +124,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
#define SUBSHELL_IGNTRAP 0x100 /* subshell should reset trapped signals from trap_handler */
/* A structure which represents a word. */
typedef struct word_desc {
......
......@@ -1547,6 +1547,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
clear_pending_traps ();
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
/* Note that signal handlers have been reset, so we should no longer
reset the handler and resend trapped signals to ourselves. */
subshell_environment &= ~SUBSHELL_IGNTRAP;
/* We are in a subshell, so forget that we are running a trap handler or
that the signal handler has changed (we haven't changed it!) */
......@@ -4332,7 +4335,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
already_forked = 1;
cmdflags |= CMD_NO_FORK;
subshell_environment = SUBSHELL_FORK; /* XXX */
/* We redo some of what make_child() does with SUBSHELL_IGNTRAP */
subshell_environment = SUBSHELL_FORK|SUBSHELL_IGNTRAP; /* XXX */
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
subshell_environment |= SUBSHELL_PIPE;
if (async)
......@@ -4586,6 +4590,7 @@ run_builtin:
trap strings if we run trap to change a signal disposition. */
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
subshell_environment &= ~SUBSHELL_IGNTRAP;
if (async)
{
......@@ -5526,6 +5531,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
reset_terminating_signals (); /* XXX */
/* Cancel traps, in trap.c. */
restore_original_signals ();
subshell_environment &= ~SUBSHELL_IGNTRAP;
#if defined (JOB_CONTROL)
FREE (p);
......
......@@ -2220,6 +2220,8 @@ make_child (command, flags)
signals to the default state for a new process. */
pid_t mypid;
subshell_environment |= SUBSHELL_IGNTRAP;
/* If this ends up being changed to modify or use `command' in the
child process, go back and change callers who free `command' in
the child process when this returns. */
......
......@@ -575,6 +575,8 @@ make_child (command, flags)
last_asynchronous_pid = getpid ();
#endif
subshell_environment |= SUBSHELL_IGNTRAP;
default_tty_job_signals ();
}
else
......
No preview for this file type
This diff is collapsed.
No preview for this file type
This diff is collapsed.
......@@ -55,7 +55,8 @@
# include "bashhist.h"
#endif
extern void initialize_siglist ();
extern void initialize_siglist PARAMS((void));
extern void set_original_signal PARAMS((int, SigHandler *));
#if !defined (JOB_CONTROL)
extern void initialize_job_signals PARAMS((void));
......@@ -255,6 +256,13 @@ initialize_terminating_signals ()
sigaction (XSIG (i), &act, &oact);
XHANDLER(i) = oact.sa_handler;
XSAFLAGS(i) = oact.sa_flags;
#if 0
set_original_signal (XSIG(i), XHANDLER(i)); /* optimization */
#else
set_original_signal (XSIG(i), act.sa_handler); /* optimization */
#endif
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
/* XXX - should we do this for interactive shells, too? */
......
......@@ -5951,6 +5951,7 @@ process_substitute (string, open_for_read_in_child)
free_pushed_string_input ();
/* Cancel traps, in trap.c. */
restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
subshell_environment &= ~SUBSHELL_IGNTRAP;
QUIT; /* catch any interrupts we got post-fork */
setup_async_signals ();
#if 0
......@@ -6382,6 +6383,7 @@ command_substitute (string, quoted, flags)
}
QUIT; /* catch any interrupts we got post-fork */
subshell_environment |= SUBSHELL_RESETTRAP;
subshell_environment &= ~SUBSHELL_IGNTRAP;
}
#if defined (JOB_CONTROL)
......
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
......
......@@ -11,93 +11,95 @@ declare -fr func
unset: usage: unset [-f] [-v] [-n] [name ...]
./errors.tests: line 55: unset: func: cannot unset: readonly function
./errors.tests: line 58: declare: func: readonly function
./errors.tests: line 62: unset: XPATH: cannot unset: readonly variable
./errors.tests: line 68: unset: cannot simultaneously unset a function and a variable
./errors.tests: line 71: declare: -z: invalid option
./errors.tests: line 62: declare: -a: invalid option
./errors.tests: line 63: declare: -i: invalid option
./errors.tests: line 67: unset: XPATH: cannot unset: readonly variable
./errors.tests: line 73: unset: cannot simultaneously unset a function and a variable
./errors.tests: line 76: declare: -z: invalid option
declare: usage: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
./errors.tests: line 73: declare: `-z': not a valid identifier
./errors.tests: line 74: declare: `/bin/sh': not a valid identifier
./errors.tests: line 78: declare: cannot use `-f' to make functions
./errors.tests: line 81: exec: -i: invalid option
./errors.tests: line 78: declare: `-z': not a valid identifier
./errors.tests: line 79: declare: `/bin/sh': not a valid identifier
./errors.tests: line 83: declare: cannot use `-f' to make functions
./errors.tests: line 86: exec: -i: invalid option
exec: usage: exec [-cl] [-a name] [command [argument ...]] [redirection ...]
./errors.tests: line 85: export: XPATH: not a function
./errors.tests: line 88: break: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 89: continue: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 92: shift: label: numeric argument required
./errors.tests: line 97: shift: too many arguments
./errors.tests: line 103: let: expression expected
./errors.tests: line 106: local: can only be used in a function
./errors.tests: line 109: logout: not login shell: use `exit'
./errors.tests: line 112: hash: notthere: not found
./errors.tests: line 115: hash: -v: invalid option
./errors.tests: line 90: export: XPATH: not a function
./errors.tests: line 93: break: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 94: continue: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 97: shift: label: numeric argument required
./errors.tests: line 102: shift: too many arguments
./errors.tests: line 108: let: expression expected
./errors.tests: line 111: local: can only be used in a function
./errors.tests: line 114: logout: not login shell: use `exit'
./errors.tests: line 117: hash: notthere: not found
./errors.tests: line 120: hash: -v: invalid option
hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
./errors.tests: line 119: hash: hashing disabled
./errors.tests: line 122: export: `AA[4]': not a valid identifier
./errors.tests: line 123: readonly: `AA[4]': not a valid identifier
./errors.tests: line 126: unset: [-2]: bad array subscript
./errors.tests: line 130: AA: readonly variable
./errors.tests: line 134: AA: readonly variable
./errors.tests: line 142: shift: 5: shift count out of range
./errors.tests: line 143: shift: -2: shift count out of range
./errors.tests: line 146: shopt: no_such_option: invalid shell option name
./errors.tests: line 147: shopt: no_such_option: invalid shell option name
./errors.tests: line 150: umask: 09: octal number out of range
./errors.tests: line 151: umask: `:': invalid symbolic mode character
./errors.tests: line 152: umask: `:': invalid symbolic mode operator
./errors.tests: line 155: umask: -i: invalid option
./errors.tests: line 124: hash: hashing disabled
./errors.tests: line 127: export: `AA[4]': not a valid identifier
./errors.tests: line 128: readonly: `AA[4]': not a valid identifier
./errors.tests: line 131: unset: [-2]: bad array subscript
./errors.tests: line 135: AA: readonly variable
./errors.tests: line 139: AA: readonly variable
./errors.tests: line 147: shift: 5: shift count out of range
./errors.tests: line 148: shift: -2: shift count out of range
./errors.tests: line 151: shopt: no_such_option: invalid shell option name
./errors.tests: line 152: shopt: no_such_option: invalid shell option name
./errors.tests: line 155: umask: 09: octal number out of range
./errors.tests: line 156: umask: `:': invalid symbolic mode character
./errors.tests: line 157: umask: `:': invalid symbolic mode operator
./errors.tests: line 160: umask: -i: invalid option
umask: usage: umask [-p] [-S] [mode]
./errors.tests: line 159: umask: `u': invalid symbolic mode character
./errors.tests: line 168: VAR: readonly variable
./errors.tests: line 171: declare: VAR: readonly variable
./errors.tests: line 172: declare: VAR: readonly variable
./errors.tests: line 174: declare: unset: not found
./errors.tests: line 177: VAR: readonly variable
./errors.tests: command substitution: line 181: syntax error near unexpected token `)'
./errors.tests: command substitution: line 181: ` for z in 1 2 3; do )'
./errors.tests: command substitution: line 182: syntax error near unexpected token `done'
./errors.tests: command substitution: line 182: ` for z in 1 2 3; done )'
./errors.tests: line 184: cd: HOME not set
./errors.tests: line 185: cd: /tmp/xyz.bash: No such file or directory
./errors.tests: line 187: cd: OLDPWD not set
./errors.tests: line 188: cd: /bin/sh: Not a directory
./errors.tests: line 190: cd: /tmp/cd-notthere: No such file or directory
./errors.tests: line 193: .: filename argument required
./errors.tests: line 164: umask: `u': invalid symbolic mode character
./errors.tests: line 173: VAR: readonly variable
./errors.tests: line 176: declare: VAR: readonly variable
./errors.tests: line 177: declare: VAR: readonly variable
./errors.tests: line 179: declare: unset: not found
./errors.tests: line 182: VAR: readonly variable
./errors.tests: command substitution: line 186: syntax error near unexpected token `)'
./errors.tests: command substitution: line 186: ` for z in 1 2 3; do )'
./errors.tests: command substitution: line 187: syntax error near unexpected token `done'
./errors.tests: command substitution: line 187: ` for z in 1 2 3; done )'
./errors.tests: line 189: cd: HOME not set
./errors.tests: line 190: cd: /tmp/xyz.bash: No such file or directory
./errors.tests: line 192: cd: OLDPWD not set
./errors.tests: line 193: cd: /bin/sh: Not a directory
./errors.tests: line 195: cd: /tmp/cd-notthere: No such file or directory
./errors.tests: line 198: .: filename argument required
.: usage: . filename [arguments]
./errors.tests: line 194: source: filename argument required
./errors.tests: line 199: source: filename argument required
source: usage: source filename [arguments]
./errors.tests: line 197: .: -i: invalid option
./errors.tests: line 202: .: -i: invalid option
.: usage: . filename [arguments]
./errors.tests: line 200: set: -q: invalid option
./errors.tests: line 205: set: -q: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
./errors.tests: line 203: enable: sh: not a shell builtin
./errors.tests: line 203: enable: bash: not a shell builtin
./errors.tests: line 206: shopt: cannot set and unset shell options simultaneously
./errors.tests: line 209: read: var: invalid timeout specification
./errors.tests: line 212: read: `/bin/sh': not a valid identifier
./errors.tests: line 215: VAR: readonly variable
./errors.tests: line 218: readonly: -x: invalid option
./errors.tests: line 208: enable: sh: not a shell builtin
./errors.tests: line 208: enable: bash: not a shell builtin
./errors.tests: line 211: shopt: cannot set and unset shell options simultaneously
./errors.tests: line 214: read: var: invalid timeout specification
./errors.tests: line 217: read: `/bin/sh': not a valid identifier
./errors.tests: line 220: VAR: readonly variable
./errors.tests: line 223: readonly: -x: invalid option
readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p
./errors.tests: line 221: eval: -i: invalid option
./errors.tests: line 226: eval: -i: invalid option
eval: usage: eval [arg ...]
./errors.tests: line 222: command: -i: invalid option
./errors.tests: line 227: command: -i: invalid option
command: usage: command [-pVv] command [arg ...]
./errors.tests: line 225: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 226: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 229: trap: NOSIG: invalid signal specification
./errors.tests: line 232: trap: -s: invalid option
./errors.tests: line 230: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 231: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 234: trap: NOSIG: invalid signal specification
./errors.tests: line 237: trap: -s: invalid option
trap: usage: trap [-lp] [[arg] signal_spec ...]
./errors.tests: line 238: return: can only `return' from a function or sourced script
./errors.tests: line 242: break: 0: loop count out of range
./errors.tests: line 246: continue: 0: loop count out of range
./errors.tests: line 251: builtin: bash: not a shell builtin
./errors.tests: line 255: bg: no job control
./errors.tests: line 256: fg: no job control
./errors.tests: line 259: kill: -s: option requires an argument
./errors.tests: line 261: kill: S: invalid signal specification
./errors.tests: line 263: kill: `': not a pid or valid job spec
./errors.tests: line 243: return: can only `return' from a function or sourced script
./errors.tests: line 247: break: 0: loop count out of range
./errors.tests: line 251: continue: 0: loop count out of range
./errors.tests: line 256: builtin: bash: not a shell builtin
./errors.tests: line 260: bg: no job control
./errors.tests: line 261: fg: no job control
./errors.tests: line 264: kill: -s: option requires an argument
./errors.tests: line 266: kill: S: invalid signal specification
./errors.tests: line 268: kill: `': not a pid or valid job spec
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
./errors.tests: line 268: set: trackall: invalid option name
./errors.tests: line 272: xx: readonly variable
./errors.tests: line 273: set: trackall: invalid option name
./errors.tests: line 277: xx: readonly variable
1
./errors1.sub: line 14: .: -i: invalid option
.: usage: . filename [arguments]
......@@ -197,4 +199,4 @@ ok 6
bash: line 1: return: can only `return' from a function or sourced script
after return
bash: line 1: return: can only `return' from a function or sourced script
./errors.tests: line 299: `!!': not a valid identifier
./errors.tests: line 304: `!!': not a valid identifier
......@@ -57,6 +57,11 @@ unset -f func
declare -fr func
declare -f +r func
# cannot use declare -f in combination with other attributes
a() { echo a; }
declare -f -a a
declare -f -i b c
XPATH=$PATH
declare -r XPATH
unset -v XPATH
......
......@@ -348,6 +348,10 @@ declare -a v=([1]="1")
declare -a v=([0]="0" [1]="1")
declare -n n="v[1]"
declare -a v=([0]="0")
./nameref15.sub: line 120: warning: xref: removing nameref attribute
declare -a xref=([1]="one")
./nameref15.sub: line 126: warning: xref: removing nameref attribute
declare -a xref=([1]="one")
declare -n r1="y"
declare -n r2="x"
./nameref16.sub: line 25: typeset: x: not found
......@@ -440,6 +444,8 @@ declare -n foo="bar"
declare -- bar
declare -- foo="bar"
declare -- bar
8
declare -n ivar="foo"
declare -a v=([0]="Y")
r: <Y>
v: <Y>
......@@ -483,3 +489,24 @@ declare -n ref="var"
declare -ai var=([1]="0")
declare -n ref="var"
declare -- var="1"
a string with spaces
many spaces
declare -n foo="bar[0]"
declare -a bar=([0]=" still more spaces")
declare -n foo="bar[0]"
declare -a bar=([0]="spaces still more spaces")
./nameref22.sub: line 50: declare: array: reference variable cannot be an array
./nameref22.sub: line 53: declare: array[128]: reference variable cannot be an array
declare -a array=([0]="one" [1]="two" [2]="three")
declare -- array="(one two three)"
declare -a array=([0]="one" [1]="two" [2]="three")
./nameref22.sub: line 69: declare: `(one two three)': invalid variable name for name reference
./nameref22.sub: line 70: declare: array: reference variable cannot be an array
declare -a array=([0]="zero")
./nameref22.sub: line 74: declare: array: reference variable cannot be an array
declare -a array=([0]="one" [1]="two" [2]="three")
./nameref22.sub: line 79: declare: array: reference variable cannot be an array
declare -a array
declare -ai array=([0]="one")
declare -a array=([0]="zero")
declare -a array=([0]="one" [1]="two" [2]="three")
......@@ -115,3 +115,13 @@ v=(0 1)
declare -n n=v[1]
unset n
declare -p n v
declare -n xref
declare -a xref[1]=one
declare -p xref
unset xref
declare -n xref
xref=array
declare -a xref[1]=one
declare -p xref
......@@ -62,3 +62,12 @@ declare bar
declare -p foo bar
declare +n foo
declare -p foo bar
# but when we add the nameref attribute, we remove other attributes
declare -i ivar
ivar=4+4
echo $ivar
declare -n ivar=foo
declare -p ivar
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
declare -n foo=bar
declare foo='a string with spaces'
echo $foo
unset foo
declare foo+='many spaces'
echo $foo
unset foo # unsets bar
unset -n foo
declare -a bar
declare -n foo='bar[0]'
declare foo+=' still more spaces'
declare -p foo bar
unset -n foo
unset bar
declare -a bar
declare -n foo='bar[0]'
declare foo=spaces
declare foo+=' still more spaces'
declare -p foo bar
unset -n foo
unset bar
ray=ray
declare -a array
array[0]=zero
declare -n array
unset array
declare -n array[128]
unset array
declare -a array='(one two three)'
declare -p array
unset array
declare array='(one two three)'
declare -p array
unset array
declare -a ar$ray='(one two three)'
declare -p ar$ray
unset array
declare -a array=(zero)
declare -n array='(one two three)'
declare -n array=three
declare -p array
unset array
declare -n array=(one two three)
declare -p array
unset array
declare -a array
declare -n array=one
declare -p array
unset array
array=one
declare -i array[64];
declare -p array
unset array
declare -a array=zero
declare -p array
unset array
declare -a array
declare array='(one two three)'
declare -p array
unset array
......@@ -481,6 +481,32 @@ trap_handler (sig)
SIGRETURN (0);
}
/* This means we're in a subshell, but have not yet reset the handler for
trapped signals. We're not supposed to execute the trap in this situation;
we should restore the original signal and resend the signal to ourselves
to preserve the Posix "signal traps that are not being ignored shall be
set to the default action" semantics. */
if ((subshell_environment & SUBSHELL_IGNTRAP) && trap_list[sig] != (char *)IGNORE_SIG)
{
sigset_t mask;
/* Paranoia */
if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
original_signals[sig] = SIG_DFL;
restore_signal (sig);
/* Make sure we let the signal we just caught through */
sigemptyset (&mask);
sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
sigdelset (&mask, sig);
sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
kill (getpid (), sig);
SIGRETURN (0);
}
if ((sig >= NSIG) ||
(trap_list[sig] == (char *)DEFAULT_SIG) ||
(trap_list[sig] == (char *)IGNORE_SIG))
......