aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-12-30 22:31:30 +1300
committerTom Ryder <tom@sanctum.geek.nz>2016-12-30 22:42:56 +1300
commit0d79eeb3ab41cf49310ec53e6cf55ccbfe2f7e31 (patch)
tree7d49a185ae556ee2a89818cab4d6d85747696875
parentAdd environment variable (diff)
downloaddotfiles-0d79eeb3ab41cf49310ec53e6cf55ccbfe2f7e31.tar.gz
dotfiles-0d79eeb3ab41cf49310ec53e6cf55ccbfe2f7e31.zip
Fix a zsh-as-sh/ksh-specific issue
Very niche, but interesting to fix anyway
-rw-r--r--ISSUES.markdown5
-rw-r--r--Makefile5
-rw-r--r--sh/profile8
-rw-r--r--zsh/profile.d/zsh.sh28
4 files changed, 40 insertions, 6 deletions
diff --git a/ISSUES.markdown b/ISSUES.markdown
index 6316f0ec..cd21a33f 100644
--- a/ISSUES.markdown
+++ b/ISSUES.markdown
@@ -20,8 +20,3 @@ Known issues
* The directory navigation tools may not be handling directories with
terminal newlines in their names due to subshell expansion chomping them;
could maybe fix this by adding a slash to what's returned
-* zsh when invoked as sh does not source ENV at the end of ~/.profile if it's
- set *during* the profile script, only if it was set when the shell started.
- I can't find anything in the POSIX spec that says this isn't allowed, but
- all the plain sh(1)es I've tried (and Bash/ksh93 as sh) do what I expect.
- Would be good to work out why this is and work around it if it's by design.
diff --git a/Makefile b/Makefile
index da6b043a..60fec019 100644
--- a/Makefile
+++ b/Makefile
@@ -394,7 +394,10 @@ install-yash : check-yash install-sh
install -pm 0644 -- yash/yashrc.d/* "$(HOME)"/.yashrc.d
install-zsh : check-zsh install-sh
- install -m 0755 -d -- "$(HOME)"/.zshrc.d
+ install -m 0755 -d -- \
+ "$(HOME)"/.profile.d \
+ "$(HOME)"/.zshrc.d
+ install -pm 0644 -- zsh/profile.d/* "$(HOME)"/.profile.d
install -pm 0644 -- zsh/zprofile "$(HOME)"/.zprofile
install -pm 0644 -- zsh/zshrc "$(HOME)"/.zshrc
install -pm 0644 -- zsh/zshrc.d/* "$(HOME)"/.zshrc.d
diff --git a/sh/profile b/sh/profile
index 5d9c80bf..dc145d85 100644
--- a/sh/profile
+++ b/sh/profile
@@ -12,3 +12,11 @@ if [ -f "$HOME"/.shinit ] ; then
ENV=$HOME/.shinit
export ENV
fi
+
+# If ENV_FORCE is set and we're interactive, source ENV explicitly
+# At the moment this is just for zsh-as-ksh/sh
+if [ -n "$ENV_FORCE" ] ; then
+ case $- in *i*)
+ [ -f "$ENV" ] && . "$ENV" ;;
+ esac
+fi
diff --git a/zsh/profile.d/zsh.sh b/zsh/profile.d/zsh.sh
new file mode 100644
index 00000000..47de6d4d
--- /dev/null
+++ b/zsh/profile.d/zsh.sh
@@ -0,0 +1,28 @@
+# Zsh before version 5.3.0 emulating POSIX sh(1) or Korn shell only sources the
+# interactive shell startup file described in ENV if it's set after
+# /etc/profile is sourced, but before ~/.profile is. The other shells I have
+# tried (including modern shells emulating POSIX sh(1)) wait until after
+# ~/.profile is read. This seems to have been fixed in Zsh commit ID fde365e,
+# which was followed by release 5.3.0.
+
+# Is this zsh masquerading as sh/ksh?
+[ -n "$ZSH_VERSION" ] || return
+case $ZSH_NAME in
+ sh|ksh) ;;
+ *) return ;;
+esac
+
+# Iterate through the zsh version number to see if it's at least 5.3.0; if not,
+# we'll have ~/.profile force sourcing $ENV
+if ! (
+ zvs=$ZSH_VERSION
+ for fv in 5 3 0 ; do
+ zv=${zvs%%[!0-9]*}
+ [ "$((zv > fv))" -eq 1 ] && exit 0
+ [ "$((zv < fv))" -eq 1 ] && exit 1
+ zvs=${zvs#*.}
+ [ -n "$zvs" ] || exit 0
+ done
+) ; then
+ ENV_FORCE=1
+fi