1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

More fixes for subshell directory handling (re: 7bab9508, 5ee290c7)

This commit fixes what are hopefully the two final aspects of #153:

1. If the present working directory does not exist (was moved or
   deleted) upon entering a virtual subshell, no PWD directory path
   is saved. Since restoring the state after exiting a virtual
   subshell is contingent on a previous PWD path existing, this
   resulted in entire aspects of the virtual subshell, such as the
   subshell function tree, not being cleaned up.
2. A separate problem is that 'cd ..' does not update PWD or OLDPWD
   when run from a nonexistent directory.

A reproducer exposing both problems is:

$ mkdir test
$ cd test
$ ksh -c '(subfn() { BAD; }; cd ..; echo subPWD==$PWD);
			typeset -f subfn; echo mainPWD==$PWD'
subPWD==/usr/local/src/ksh93/ksh/test
subfn() { BAD; };mainPWD==/usr/local/src/ksh93/ksh/test

Expected output:
subPWD==/usr/local/src/ksh93/ksh
mainPWD==/usr/local/src/ksh93/ksh/test

src/cmd/ksh93/bltins/cd_pwd.c:
- If path_pwd() fails to get the PWD (usually it no longer exists),
  don't set $OLDPWD to '.' as that is pointless; use $PWD instead.
  After cd'ing from a nonexistent directory, 'cd -' *should* fail
  and should not be equivalent to 'cd .'.
- Remove a redundant check for (!oldpwd) where it is always set.
- Do not prematurely return without setting PWD or OLDPWD if
  pathcanon() fails to canonicalise a nonexistent directory.
  Instead, fall back to setting PWD to the result of getcwd(3).

src/cmd/ksh93/sh/subshell.c:
- Minor stylistic adjustment. Some NULL macros sneaked in. This
  historic code base does not use them (yet); change to NIL(type*).
- sh_subshell(): Fix logic for determining whether to save/restore
  subshell state.
  1. When saving, 'if(!comsub || !shp->subshare)' is redundant;
     'if(!shp->subshare)' should be enough. If we're not in a
     subshare, state should be saved.
  2. When restoring, 'if(sp->shpwd)' is just nonsense as there is
     no guarantee that the PWD exists upon entering a subshell.
     Simply use the same 'if(!shp->subshare)'. Add an extra check
     for sp->pwd to avoid a possible segfault. Always restore the
     PWD on subshell exit and not only if shp->pwd is set.
- sh_subshell(): Issue fatal errors in libast's "panic" format.

src/cmd/ksh93/tests/builtins.sh:
- Adjust a relevant test to run err_exit() outside of the subshell
  so that any error is counted in the main shell.
- Add test for problem 2 described at the top.

src/cmd/ksh93/tests/subshell.sh:
- Add test for problems 1 and 2 based on reproducer above.

Resolves: https://github.com/ksh93/ksh/issues/153
This commit is contained in:
Martijn Dekker 2021-04-18 23:28:50 +01:00
parent b0a6c1bde5
commit feaf718f16
4 changed files with 67 additions and 38 deletions

View file

@ -671,8 +671,8 @@ then (
mv t1 t2
mkdir t1
)
[[ -f real_t1 ]] || err_exit 'real_t1 not found after parent directory renamed in subshell'
)
[[ -f real_t1 ]]
) || err_exit 'real_t1 not found after parent directory renamed in subshell'
fi
cd "$tmp"
@ -1206,5 +1206,16 @@ then exp=' version cat (*) ????-??-??'
else warning 'skipping path-bound builtin tests: builtin /opt/ast/bin/cat not found'
fi
# ======
# part of https://github.com/ksh93/ksh/issues/153
mkdir "$tmp/deleted"
cd "$tmp/deleted"
tmp=$tmp "$SHELL" -c 'cd /; rmdir "$tmp/deleted"'
exp=$PWD
got=$("$SHELL" -c 'cd /; echo "$OLDPWD"' 2>&1)
[[ $got == "$exp" ]] || err_exit "OLDPWD not correct after cd'ing from a nonexistent PWD" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
cd "$tmp"
# ======
exit $((Errors<125?Errors:125))