mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Fix multiple bugs when using 'alias -p' to print aliases (#398)
This commit was originally intended to fix just one bug with shcomp's handling of 'alias -p', but while fixing that I found a large number of related issues in the alias command's -p, -t and -x options. The current patch provides bugfixes for all of the bugs listed below: 1) Listing aliases in a script with 'alias -p' or 'alias' broke shcomp's bytecode output: https://github.com/ksh93/ksh/issues/87#issuecomment-813819122 2) Listing individual aliases with the -p option doesn't work: $ alias foo=bar bar=foo $ alias foo foo=bar $ alias -p foo # No output 3) Listing specific tracked aliases with -pt does not display them in a reusable format, but rather adds another tracked alias: $ hash -r cat vi $ alias -pt vi # No output $ alias -pt rm $ alias -t cat=/usr/bin/cat rm=/usr/bin/rm vi=/usr/bin/vi 4) Listing all tracked aliases with -pt does not output them in a reusable format (the resulting command printed only creates a normal alias, which is different from a tracked alias): $ hash -r cat $ alias -pt alias cat=/usr/bin/cat # Expected 'alias -t cat' 5) Listing a non-existent alias with -p doesn't cause an error: $ unalias -a $ alias -p notanalias # No output $ echo $? 0 $ alias notanalias notanalias: alias not found $ echo $? 1 $ hash -r $ alias -pt notacommand # No output $ echo $? 0 6) Attempting to list 256 non-existent aliases results in exit status zero: $ unalias -a $ alias $(awk -v ORS= 'BEGIN { for(i=0;i<256;i++) print "x "; }') x: alias not found --cut error message-- $ echo $? 0 Changes: - typeset.c: Avoid printing anything while shcomp is compiling a script. This is needed because the alias command is run by shcomp to prevent parsing issues. - b_alias(): To avoid adding tracked aliases with -pt, set tdata.aflag to '+' so that setall() and other related functions only list tracked aliases. - b_alias(): Set tdata.pflag to 1 so that setall() and other functions recognize -p was passed. - print_value(): Add support for listing specific aliases with 'alias -p'. - setall(): To avoid any issues with zombie tracked aliases (see also the regression tests) ignore tracked alias nodes marked with the NV_NOALIAS attribute. This bit is set for tracked alias nodes by the nv_rehash() function. - setall(): For backward compatibility, continue incrementing the exit status for each invalid alias and tracked alias passed. This was already how alias behaved when listing aliases without -p, so using -p shouldn't cause a change in behavior: $ unalias -a $ alias foo bar foo: alias not found bar: alias not found $ echo $? 2 To fix bug 6, the exit status is set to one if an enforced 8-bit exit status would be zero. - print_namval(): Set the prefix to 'alias -t' so that listing tracked aliases with 'alias -pt' works correctly. - data/msg.c and include/name.h: Add an error message for when 'alias -pt' doesn't find a tracked alias. - tests/alias.sh: Add a ton of regression tests for the bugs fixed in this commit.
This commit is contained in:
parent
feeb62d15f
commit
f7213f03a2
8 changed files with 245 additions and 10 deletions
|
|
@ -104,5 +104,176 @@ unalias foo && err_exit 'unalias should return non-zero when a previously set al
|
|||
err=$(set +x; { "$SHELL" -i -c 'unalias history; unalias r'; } 2>&1) && [[ -z $err ]] \
|
||||
|| err_exit "the 'history' and 'r' aliases can't be removed (got $(printf %q "$err"))"
|
||||
|
||||
# ======
|
||||
# Listing aliases in a script shouldn't break shcomp bytecode
|
||||
exp="alias foo='bar('
|
||||
alias four=4
|
||||
alias three=3
|
||||
alias two=2
|
||||
foo='bar('
|
||||
foo='bar('
|
||||
four=4
|
||||
three=3
|
||||
two=2
|
||||
foo='bar('
|
||||
four=4
|
||||
three=3
|
||||
two=2
|
||||
noalias: alias not found
|
||||
ls=$(whence -p ls)
|
||||
alias -t ls"
|
||||
alias_script=$tmp/alias_script.sh
|
||||
cat > "$alias_script" << EOF
|
||||
unalias -a
|
||||
alias foo='bar('
|
||||
alias two=2
|
||||
alias three=3
|
||||
alias four=4
|
||||
alias -p
|
||||
alias foo
|
||||
alias -x
|
||||
alias
|
||||
alias noalias
|
||||
alias -t ls
|
||||
alias -t
|
||||
alias -pt
|
||||
EOF
|
||||
got=$(set +x; redirect 2>&1; $SHELL <($SHCOMP "$alias_script"))
|
||||
[[ $exp == $got ]] || err_exit "Listing aliases corrupts shcomp bytecode" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
# Specifying an alias with 'alias -p' should print that alias in a reusable form
|
||||
exp='alias foo=BAR'
|
||||
got=$(
|
||||
alias foo=BAR bar=FOO
|
||||
alias -p foo
|
||||
)
|
||||
[[ $exp == $got ]] || err_exit "Specifying an alias with 'alias -p' doesn't work" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
got=$(
|
||||
hash -r cat
|
||||
alias -tx
|
||||
alias -ptx
|
||||
alias -ptx cat
|
||||
alias -ptx nosuchcommand
|
||||
)
|
||||
[[ -z $got ]] || err_exit "The -x option should prevent output when combined with -t" \
|
||||
"(got $(printf %q "$got"))"
|
||||
|
||||
# Listing members of the hash table with 'alias -pt' should work
|
||||
exp='alias -t cat
|
||||
vi: tracked alias not found
|
||||
alias -t cat
|
||||
alias -t chmod'
|
||||
got=$(
|
||||
set +x
|
||||
redirect 2>&1
|
||||
hash -r cat chmod
|
||||
alias -pt cat vi # vi shouldn't be added to the hash table
|
||||
alias -pt
|
||||
)
|
||||
[[ $exp == $got ]] || err_exit "Listing members of the hash table with 'alias -pt' doesn't work" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
# Attempting to list a non-existent alias or tracked alias should fail
|
||||
# with an error message. Note that the exit status should match the
|
||||
# number of aliases passed that don't exist.
|
||||
exp='foo: alias not found
|
||||
bar: alias not found
|
||||
nosuchalias: alias not found'
|
||||
got=$(
|
||||
set +x
|
||||
redirect 2>&1
|
||||
unalias -a
|
||||
alias foo bar nosuchalias
|
||||
)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing non-existent aliases with 'alias' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 3)) || err_exit "Listing non-existent aliases with 'alias' has wrong exit status" \
|
||||
"(expected 3, got $ret)"
|
||||
|
||||
# Same as above, but tests alias -p with a different number
|
||||
# of non-existent aliases.
|
||||
exp='foo: alias not found
|
||||
bar: alias not found
|
||||
nosuchalias: alias not found
|
||||
stillnoalias: alias not found'
|
||||
got=$(
|
||||
set +x
|
||||
redirect 2>&1
|
||||
unalias -a
|
||||
alias -p foo bar nosuchalias stillnoalias
|
||||
)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing non-existent aliases with 'alias -p' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 4)) || err_exit "Listing non-existent aliases with 'alias -p' has wrong exit status" \
|
||||
"(expected 4, got $ret)"
|
||||
|
||||
# Tracked aliases next.
|
||||
exp='rm: tracked alias not found
|
||||
ls: tracked alias not found'
|
||||
got=$(
|
||||
set +x
|
||||
redirect 2>&1
|
||||
hash -r
|
||||
alias -pt rm ls
|
||||
)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing non-existent tracked aliases with 'alias -pt' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 2)) || err_exit "Listing non-existent tracked aliases with 'alias -pt' has wrong exit status" \
|
||||
"(expected 2, got $ret)"
|
||||
|
||||
# Detect zombie aliases with 'alias'.
|
||||
exp='vi: alias not found
|
||||
chmod: alias not found'
|
||||
got=$($SHELL -c '
|
||||
hash vi chmod
|
||||
hash -r
|
||||
alias vi chmod
|
||||
' 2>&1)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing removed tracked aliases with 'alias' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 2)) || err_exit "Listing removed tracked aliases with 'alias' has wrong exit status" \
|
||||
"(expected 2, got $ret)"
|
||||
|
||||
# Detect zombie aliases with 'alias -p'.
|
||||
exp='vi: alias not found
|
||||
chmod: alias not found'
|
||||
got=$($SHELL -c '
|
||||
hash vi chmod
|
||||
hash -r
|
||||
alias -p vi chmod
|
||||
' 2>&1)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing removed tracked aliases with 'alias -p' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 2)) || err_exit "Listing removed tracked aliases with 'alias -p' has wrong exit status" \
|
||||
"(expected 2, got $ret)"
|
||||
|
||||
# Detect zombie tracked aliases.
|
||||
exp='vi: tracked alias not found
|
||||
chmod: tracked alias not found'
|
||||
got=$($SHELL -c '
|
||||
hash vi chmod
|
||||
hash -r
|
||||
alias -pt vi chmod
|
||||
' 2>&1)
|
||||
ret=$?
|
||||
[[ $exp == $got ]] || err_exit "Listing removed tracked aliases with 'alias -pt' should fail with an error message" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
((ret == 2)) || err_exit "Listing removed tracked aliases with 'alias -pt' has wrong exit status" \
|
||||
"(expected 2, got $ret)"
|
||||
|
||||
# The exit status on error must be >0, including when handling
|
||||
# 256 non-existent aliases.
|
||||
(unalias -a; alias $(integer -s i; for((i=0;i<256;i++)) do print -n "x "; done) 2> /dev/null)
|
||||
got=$?
|
||||
((got > 0)) || err_exit "Exit status is zero when alias is passed 256 non-existent aliases"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue