the `history' builtin prints error messages for certain read and write errors; implementation of new form of nofork command substitution that does not remove trailing newlines

This commit is contained in:
Chet Ramey
2026-01-18 17:48:33 -05:00
parent a6421d8419
commit 8ea1a222df
25 changed files with 2841 additions and 2399 deletions
+80 -5
View File
@@ -65,6 +65,8 @@ one two
comsub21.sub
123
123
123
0
0
123
123
@@ -73,8 +75,21 @@ Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
Mon Aug 29 20:03:02 EDT 2022
123
123
before 123
before
123
in for 123
comsub22.sub
outside before: value
@@ -87,21 +102,29 @@ outside before: value
comsub23.sub
.
declare -a a=([0]="1" [1]="2" [2]="3" [3]="4")
declare -a a=([0]="1" [1]="2" [2]="3" [3]=$'4\n')
declare -- int="2"
after here-doc: 1
[1]- Running sleep 1 &
[2]+ Running sleep 1 &
[1]- Running sleep 1 &
[2]+ Running sleep 1 &
[1]- Running sleep 1 &
[2]+ Running sleep 1 &
=
17772 26794
17772 26794
we should try rhs
comsub
and
funsub
and
newline funsub
in here-documents
after all they work here
and work here
and also here
after for
uname
after arith for
@@ -196,6 +219,8 @@ AFTER
unbalanced braces}}
combined comsubs
combined comsubs
combined nostrip comsubs
inside
after: var = inside
after: 42 var = inside
@@ -210,17 +235,67 @@ declare -- x=""
a[${ unset x;}]
declare -i x
declare -- x=""
./comsub27.sub: line 36: ${ unset x;}: arithmetic syntax error: operand expected (error token is "${ unset x;}")
./comsub27.sub: line 50: ${ unset x;}: arithmetic syntax error: operand expected (error token is "${ unset x;}")
declare -i x
declare -- SECONDS=""
declare -i SECONDS="0"
declare -- x="0"
declare -a x=([2]="a[]")
declare -ai a=()
./comsub27.sub: line 61: b[]: bad array subscript
./comsub27.sub: line 61: b[]: bad array subscript
./comsub27.sub: line 75: b[]: bad array subscript
./comsub27.sub: line 75: b[]: bad array subscript
declare -ai a=([0]="1" [1]="0" [2]="3")
declare -Ai a=()
./comsub27.sub: line 71: b[]: bad array subscript
./comsub27.sub: line 71: b[]: bad array subscript
./comsub27.sub: line 85: b[]: bad array subscript
./comsub27.sub: line 85: b[]: bad array subscript
declare -Ai a=([3]="0" [1]="0" )
comsub28.sub
AAaa
bb
cc
ddBB
aa bb cc dd
AAaa bb cc dd BB
AAaa
bb
cc
dd
BB
aa bb cc dd
aa
bb
cc
dd
aa bb cc dd
DDDDDaa bb cc dd EEEEE
DDDDDaa
bb
cc
ddEEEEE
DDDDDaa
bb
cc
dd
EEEEE
abcde
abcde
=two newlines
=
a
nested
b
a
nested
b
a
nested
b
42
42
42
+1
View File
@@ -153,3 +153,4 @@ test_runsub ./comsub24.sub
test_runsub ./comsub25.sub
test_runsub ./comsub26.sub
test_runsub ./comsub27.sub
test_runsub ./comsub28.sub
+12
View File
@@ -22,7 +22,9 @@ alias number="echo 123"
echo ${ number; }
echo $(( ${ number; } ))
echo $(( "${; number; }" ))
(( ${ number; } )) ; echo $?
(( "${; number; }" )) ; echo $?
set -o posix
echo ${ number; }
@@ -36,11 +38,17 @@ shopt -s expand_aliases
alias my_alias='echo $DATE'
echo ${ eval my_alias; }
echo ${; eval my_alias; }
echo ${ my_alias; }
echo ${; my_alias; }
echo "${; my_alias; }"
set -o posix
echo ${ eval my_alias; }
echo ${; eval my_alias; }
echo ${ my_alias; }
echo ${; my_alias; }
echo "${; my_alias; }"
set +o posix ; shopt -s expand_aliases
alias e=echo
@@ -48,7 +56,9 @@ alias v='e 123'
set -o posix
echo ${ v; }
echo "${; v; }"
echo ${ echo before ; v; }
echo "${; echo before ; v; }"
echo ${ for f in 0; do
echo in for
done; v; }
@@ -58,8 +68,10 @@ alias let='let --'
let '1 == 1'
: ${ let '1 == 1'; }
: "${; let '1 == 1'; }"
set -o posix
let '1 == 1'
: ${ let '1 == 1'; }
: "${; let '1 == 1'; }"
set +o posix ; shopt -s expand_aliases
+13 -2
View File
@@ -16,7 +16,8 @@
# make sure parsing is right within conditional commands
[[ ${ echo -n "[${ echo -n foo; }]" ; } == '[foo]' ]] || echo bad 1
[[ "${ echo -n "[${ echo -n foo; }]" ; }" == '[foo]' ]] || echo bad 1
[[ "${ echo "[${ echo foo; }]" ; }" == '[foo]' ]] || echo bad 2
[[ "${; echo -n "[${; echo -n foo; }]" ; }" == '[foo]' ]] || echo bad 3
# mix multiple calls to parse_and_execute
got=$(eval 'x=${ for i in test; do case $i in test) echo .;; esac; done; }' ; echo $x)
@@ -26,6 +27,9 @@ echo $got
: ${ a=(1 2 3 ${ echo 4;} ); }
declare -p a
unset a
: ${;a=(1 2 3 "${;echo 4;}" ); } # array element contains newline
declare -p a
unset a
# function execution with side effects
int=0
@@ -55,6 +59,9 @@ printf '%s\n' "$jl1"
jl2=${ jobs; }
printf '%s\n' "$jl2"
jl3=${; jobs; }
printf '%s=\n' "$jl3"
# nofork command substitution doesn't affect the shell's random number sequence
RANDOM=42
echo $RANDOM ${ echo $RANDOM; }
@@ -69,6 +76,8 @@ we should try rhs
${word-$(echo comsub)}
and
${word-${ echo funsub; }}
and
${word-${; echo newline funsub; }}
in here-documents
EOF
@@ -77,10 +86,12 @@ exec 4<&-
echo after all they ${word-$(echo work here)}
echo and ${word-${ echo work here; }}
echo and ${word-${; echo -n also here; }}
unset x
set -- 'a[${ break;}]'
# now two null strings as the positional parameters
set -- 'a[${ break;}]' 'a[${; break;}]'
declare -n x
for x do :; done
+1
View File
@@ -24,6 +24,7 @@ echo ${ echo unbalanced braces; }}}
echo $(echo combined ${| REPLY=comsubs; })
echo ${ echo $(echo combined ${| REPLY=comsubs; }); }
echo "${; echo $(echo combined nostrip ${| REPLY=comsubs; }); }"
var=outside
echo ${ var=inside; echo $var; }
+14
View File
@@ -1,3 +1,17 @@
# 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 -i x
x='a[${ unset x;}]'
declare -p x
+67
View File
@@ -0,0 +1,67 @@
# 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/>.
#
# tests of new funsub form that doesn't remove trailing newlines
# basic tests
# final newline removed
echo "AA${ printf '%s\n' aa bb cc dd; }BB"
# final newline not removed, newlines removed by word splitting
echo ${;printf '%s\n' aa bb cc dd; }
# final newline not removed, newlines removed by word splitting
echo AA${;printf '%s\n' aa bb cc dd; }BB
# final newline not removed, no newlines removed
echo "AA${;printf '%s\n' aa bb cc dd; }BB"
# return results from first printf, newlines removed by word splitting
echo ${;printf '%s\n' aa bb cc dd; return; echo ee ff; }
# return results from first printf, no newlines removed
printf '%s' "${;printf '%s\n' aa bb cc dd; return; echo ee ff; }"
# newlines removed by word splitting
echo ${;printf '%s\n' aa bb cc dd
}
# newlines removed by word splitting
echo DDDDD${;
printf '%s\n' aa bb cc dd
}EEEEE
# newlines not removed by word splitting, final newline removed
echo "DDDDD${
printf '%s\n' aa bb cc dd
}EEEEE"
# no newlines removed
echo "DDDDD${;
printf '%s\n' aa bb cc dd
}EEEEE"
yy=${;:;}
unset -v yy
echo ${;( echo abcde ); } # newlines removed by word splitting
printf '%s' "${;( echo abcde ); }" # no newlines removed
# no newlines removed
a==${; printf '%s' $'two newlines\n\n'; }=
echo "$a"
# no newlines removed
echo "${;echo a ; echo "${;echo nested; }"; echo b; }"
echo "${;echo a ; echo "${ echo nested; }"; echo b; }"
echo "${ echo a ; echo "${;echo nested; }"; echo b; }"
# no newlines removed
echo "${;echo $(( 24+18 )); }"
# no newlines removed, arith parsing handles it
echo $(( "${;echo 24 + 18; }"))
echo $(( "${;echo 14 + 18; }+" 10))
+7
View File
@@ -556,3 +556,10 @@ e
./history11.sub: line 71: history: 20: history position out of range
./history11.sub: line 72: history: -30: history position out of range
history12.sub
./history12.sub: line 32: history: notthere: read error: No such file or directory
./history12.sub: line 38: history: notthere: read error: Permission denied
./history12.sub: line 40: history: .: read error: Is a directory
./history12.sub: line 46: history: histdir: write error: Is a directory
./history12.sub: line 47: history: histdir/notthere: write error: Permission denied
./history12.sub: line 51: history: nodir/notthere: write error: No such file or directory
+1
View File
@@ -139,3 +139,4 @@ test_runsub ./history8.sub
test_runsub ./history9.sub
test_runsub ./history10.sub
test_runsub ./history11.sub
test_runsub ./history12.sub
+51
View File
@@ -0,0 +1,51 @@
# 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/>.
#
# error messages on history file read and write errors
: ${TMPDIR:=/tmp}
cd $TMPDIR || exit 1
FILENAME=notthere
DIRNAME=histdir
unset HISTTIMEFORMAT
rm -f $FILENAME
trap 'rm -f $FILENAME ; rm -rf $DIRNAME' 0 1 2 3 6 15
HISTFILE=/dev/null
set -o history
history -r /dev/null # should succeed
history -r notthere # failure
history -w # should succeed
history -w $FILENAME # should succeed
chmod 200 $FILENAME
history -r $FILENAME
history -r .
mkdir $DIRNAME
touch $DIRNAME/$FILENAME
chmod 555 $DIRNAME
history -w $DIRNAME
history -w $DIRNAME/$FILENAME
chmod u+w $DIRNAME
history -w nodir/$FILENAME