At Mon, 30 Sep 2024 22:52:18 +0200, tlaronde%kergis.com@localhost wrote: Subject: Re: interactive shell detection in shrc > > But, if I'm not mistaken, the discussion was about testing if a shell > is interactive, that is, "inheriting" whatever has been set and > testing it. Indeed, so by tradition a Unix shell session is started by one of any number of mechanisms, including from "xterm -ls", and has a $SHELL assigned and invoked, and then keeps a constant value for $SHELL until that session ends. Everything outside those parameters is out of scope, such as manually running some other shell program. This thread started to discuss detecting an interactive shell in the likes of ~/.shrc, i.e. in the script file referenced by the expansion of $ENV, specifically for NetBSD sh(1). This is of particular importance for NetBSD's sh(1) (and also NetBSD ksh(1)) because it(they) always source the expansion of $ENV even for non-interactive shells. $ENV is particularly useful for customising interactive sub-shells that one might start from within some other application. My favourite example, and the method I use for testing this condition, is the "shell" command in mail(1), or the ":sh" command in vi(1). However for for non-interactive shells started by other programs, such as make(1), i.e. typically via system(3), one usually wants to avoid customisations! For example that's the difference between mail(1)'s "shell" and "|" commands -- the first is interactive, the second is not. That's because such customisations may both impact performance of, and possibly also "corrupt" the expected behaviour of, the shell in such a way as to interfere with the proper and expected execution of non-interactive programs. Of course, as kre suggested, by always sourcing the result of $ENV expansion NetBSD sh(1) offers the option of purposefully modifying the behaviour of non-interactive shells, perhaps so that one can work around bugs, or test new features, etc. Note there is also the concept of a shell instance being a "login shell", which generally amongst unixy shells suitable for login session also affects which files it might source by default upon invocation, such as /etc/profile and ~/.profile. Traditionally this was all one might desire for shell customisation. However it restricted the ability to make use of certain features in more featureful shells such as ksh which required setup on a per-invocation basis (e.g. for things like command aliases which cannot be exported via the environment), thus the invention of $ENV and the eventual restriction in POSIX of only sourcing $ENV for interactive (sub)shells such as those started from mail(1) or vi(1). I'll also note in passing that the need for interactive sub-shells has been greatly reduced to almost nil by the advent of job control as well as the proliferation of multi-session tools such as windowing environments or the likes of tmux(1) and screen(1). If I'm not mistaken NetBSD's sh(1) and ksh(1) (and pkgsrc pdksh(1) some other pdksh derivatives, but not mksh(1)) are pretty much alone in always expanding and sourcing $ENV (or some default file) even when invoked non-interactively. Bash(1) has $BASH_ENV, which is always sourced, but bash(1) also supports $ENV in the POSIX manner for interactive-only shells. In my vague memory AT&T Ksh once always sourced $ENV (thus why pdksh(1) does as well), but ksh93(1) from pkgsrc/shells/ast-ksh is now documented to have the POSIX behaviour. Schily's bosh(1) (and obviously his pbosh(1)) also are POSIX compliant. NetBSD's sh(1) is also pretty much alone in not having a default filename to be used if $ENV is not set (and not null(empty)). NetBSD ksh(1), pdksh(1), and even mksh(1) if I understand it correctly, _do_ on the other hand have default files which are used if $ENV is not set (and not null, i.e. empty). So, to sum up, for NetBSD sh(1) and ksh(1) specifically the following in a script file referenced by the expansion of $ENV is sufficient: case "$-" in *i*) ;; *) return ;; esac However for those of us who use other shells, either because they are not (yet) compatible with POSIX Issue 8 (which is when the mandate for including 'i' in $- first appears), or because of the second part of the following rule in POSIX, we require a wee bit more. If the -i option is present, or if there are no operands and the shell's standard input and standard error are attached to a terminal, the shell is considered to be interactive. To handle the second part of this rule we must compare $0 and $SHELL, as the presence of any operands upon invocation will have changed $0 to something other than $SHELL. Also because of a long-standing "oversight" in NetBSD sh(1) some shells we might ignore the stderr part of the test and just consider stdin (as that's really all that matters for "interactivity", right?). So this is a more portable, compatible, and hopefully sufficient test: sh_is_interactive=false case "$-" in *i*) sh_is_interactive=true ;; esac if [ -t 0 -a "$0" = "$SHELL" ]; then sh_is_interactive=true fi if $sh_is_interactive; then : OK else return fi It is need only in files referenced by $ENV, or any sourced by default if $ENV is not set, by shells that always source those files even for non-interactive shells. On stock NetBSD this is just sh(1) and ksh(1), but it may also include older AT&T Ksh, other pdksh(1), etc. It would matter for the Heirloom Shell, but since it doesn't support $ENV at all, it does not actually matter for it. -- Greg A. Woods <gwoods%acm.org@localhost> Kelowna, BC +1 250 762-7675 RoboHack <woods%robohack.ca@localhost> Planix, Inc. <woods%planix.com@localhost> Avoncote Farms <woods%avoncote.ca@localhost>
Attachment:
pgpnqO3gnSbfz.pgp
Description: OpenPGP Digital Signature