From: Miguel Landaeta Subject: bin/ksh: don't let local EDITOR/VISUAL assignments change edit mode To: tech@openbsd.org Date: Fri, 3 Jul 2026 10:51:39 +0000 Hi, With the default ksh configuration, if you ever decide to run a command like: EDITOR=vi true Or, more realistically, something like this (how I stumbled upon this bug): EDITOR=vim git rebase -i HEAD~50 Once the child process returns, the shell ends up stuck in whichever mode the local assignment selected, breaking emacs bindings such as up/down history and incremental search (^R). You can work around this by running: set -o emacs However, I think a local assignment only exists to influence the child process's environment; the interactive shell's own line-editing mode has no reason to react to it, and getting silently and permanently stuck in the wrong mode is frankly annoying behavior. Please see the patch below, is this an OK approach to fix this? Thanks, Miguel. diff --git a/bin/ksh/var.c b/bin/ksh/var.c index 9e0bd7c0c3f..c97c822d45f 100644 --- a/bin/ksh/var.c +++ b/bin/ksh/var.c @@ -641,9 +641,20 @@ typeset(const char *var, int set, int clr, int field, int base) strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0)) errorf("%s: restricted", tvar); - vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) : - global(tvar); - set &= ~(LOCAL|LOCAL_COPY); + { + int is_local = (set & LOCAL) != 0; + + vp = is_local ? local(tvar, (set & LOCAL_COPY) ? true : false) : + global(tvar); + set &= ~(LOCAL|LOCAL_COPY); + + /* A local EDITOR/VISUAL only affects the child process; skip it + * here because popblock() can't undo it later. */ + if (is_local && (vp->flag & SPECIAL) && + (special(vp->name) == V_EDITOR || + special(vp->name) == V_VISUAL)) + vp->flag &= ~SPECIAL; + } vpbase = (vp->flag & ARRAY) ? global(arrayname(tvar)) : vp;