[Bug 274280] Incompatible default shell configuration

From: <bugzilla-noreply_at_freebsd.org>
Date: Thu, 05 Oct 2023 17:00:07 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274280

            Bug ID: 274280
           Summary: Incompatible default shell configuration
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: conf
          Assignee: bugs@FreeBSD.org
          Reporter: tg@mirbsd.org

I’m upstream for mksh (shells/mksh in ports), and I’ve had a user report
problems on FreeBSD, which I was able to track down.

dot.shrc¹ contains commands specific to FreeBSD sh which are not POSIX
conformant nor compatible with mksh; specifically, the bind commands in lines
34ff, although the PS1 is also nōn-standard.

The problem is exacerbated by dot.profile² exporting ENV, which makes mksh look
at .shrc in the first place, which it normally would not.

Just like PS1, exporting ENV is something that should not be done. For ENV
however, there’s the option of writing the designated file in a way that is
compatible with all shells that read it (which is not an option for PS1).

My preference would be for FreeBSD to not export ENV. I understand this is most
likely too much; therefore, please add the following lines…

if test -n "$KSH_VERSION"; then
        test -e ~/.mkshrc || return 0
        . ~/.mkshrc
        return
fi

… between the comment end on line 8 and the comment beginning on line 11 to fix
this problem and MFC that to the active stable branches.

The change will defer from .shrc to .mkshrc if it exists (and if so, return its
exit status up the chain), and just return true if it doesn’t exist.

The change will make it so that, when mksh (or pdksh, oksh or AT&T ksh93,
incidentally, but the stock dot.mkshrc has a whitelist for mksh/lksh and just
returns true for all other shells) is run, the remainder of the FreeBSD .shrc
is ignored and the mksh one is used instead.

It might be useful to defer to different files, depending on what shells are
ported however this will raise complexity.

Looking at your ports tree, I’m surprised to see that 1999 pdksh is even still
present. But that can be mostly lumped together with oksh. A more complete
solution would thus be:

if test -n "${KSH_VERSION:-}"; then
        # mksh/lksh? (shells/mksh port)
        case $KSH_VERSION in
        *LEGACY\ KSH*|*MIRBSD\ KSH*)
                test -e ~/.mkshrc || return 0
                . ~/.mkshrc
                return
                ;;
        esac
        # AT&T ksh93? (shells/ast-ksh, shells/ksh, shells/ksh93)
        if (eval 'x=${.sh.version}') >/dev/null 2>&1; then
                test -e ~/.ksh93rc || return 0
                . ~/.ksh93rc
                return
        fi
        # other pdksh variants (shells/oksh, shells/pdksh)
        test -e ~/.kshrc || return 0
        . ~/.kshrc
        return
fi

This is assuming users of these shells would create the corresponding dotfiles.
There’s historic evidence for ~/.kshrc, mostly by pdksh/oksh users; there’s
none for ~/.ksh93rc TTBOMK (some, but few, seem to be using ~/.kshrc).

This leaves out GNU bash, AT&T ksh88, yash, zsh (if any of these honour $ENV).

From my shell detection utility³, they can easily be detected by:

if test -n "${BASH_VERSION:-}"; then
        …
fi

case ${YASH_VERSION:-} in
*.*)
        …
        ;;
esac

case ${ZSH_VERSION:-} in
*[0-9]*)
        …
        ;;
esac

case ${VERSION:-} in
zsh*)
        …
        ;;
esac

(the last one is for old versions of zsh and may not be necessary any more)

This leaves out AT&T ksh88, which is sensible as it’s binary-only and only
present on old Unicēs, and other sh variants like NetBSD sh, ash/dash, etc.

There *is* a dash port; dash does not support bind, and it does not set a shell
parameter to detect it; dash does read $ENV. You’ll have broken dash users, but
that’s probably not a big issue.

Unfortunately, FreeBSD /bin/sh doesn’t appear (I don’t have access to a FreeBSD
system at the moment, only a MidnightBSD system, but it seems to share /bin/sh
still) to set a variable to discern it either, so let’s just ignore dash for
now.


Note: I don’t advocate for leaving out the bind commands from .shrc instead.
Users of the other shells *will* want to be able to read their shells’ own
startup files (especially considering mksh ships such a rich one predefined),
so diverting to them is necessary.


① https://cgit.freebsd.org/src/tree/usr.bin/man/man.sh
② https://cgit.freebsd.org/src/tree/share/skel/dot.profile
③ http://www.mirbsd.org/cvs.cgi/contrib/code/Snippets/getshver?rev=HEAD

-- 
You are receiving this mail because:
You are the assignee for the bug.