Why 'script' utility require SHELL (and work fine under Linux)?

Cyrille Lefevre cyrille.lefevre-lists@laposte.net
Mon Nov 7 23:23:00 GMT 2011


Le 04/11/2011 21:22, David Sastre a écrit :
> On Fri, Nov 04, 2011 at 06:05:39AM +0100, Cyrille Lefevre wrote:
>> the base-file maintainer has been BCC'ed to add the export SHELL to
>> the /etc/profile.
>
> GNU/Linux login sets SHELL to bash, mksh, ... whilst ssh sets SHELL to
> /bin/bash, /bin/posh, /bin/mksh ...
> Given that there is no real login into cygwin (yet?), SHELL should be
> set to the expected login value.
>
> Assuming SHELL would be set and exported for login shells, i.e.,
> further (nested) callings to interactive, non-login shells would
> inherit the original (login) SHELL value (as in GNU/Linux):
>
> $ echo $SHELL
> bash
> $ mksh
> $ echo $SHELL
> bash
>
> It could be fixed for bash, zsh, and mksh. Even for nested
> calls to login shells (which GNU/Linux doesn't honor) by setting SHELL
> for every ifdef in /etc/profile. Collateral damage:
>
> -posh works OK if set as login shell in /etc/passwd, but it is broken
> when called from command line as login shell (i.e. it ignores both
> /etc/profile and ~/.profile)
> -sh thinks she's bash:
>
<snip>
>
> In short: it's not clear to me how to add this functionality
> consistently.
Hi,

well, you didn't understand what I mean, so,
let's try w/ export | grep SHELL

$ bash -l
$ echo $SHELL
/bin/bash
=> defaulted internally ?
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC="C:\\Windows\\system32\\cmd.exe"
=> no env SHELL
$ perl -MEnv -e 'print $SHELL.":".$COMSPEC'
:C:\Windows\system32\cmd.exe
$ awk 'BEGIN{print ENVIRON["SHELL"]":"ENVIRON["COMSPEC"]}'
:C:\Windows\system32\cmd.exe

ditto w/ sh (almost same as bash :-), however,
defaulted to /bin/bash instead of /bin/sh !

== posh ==

$ posh -l
$ echo $SHELL
=> no default !
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC=C:\Windows\system32\cmd.exe
export SHELL
=> empty !
$ env | grep SHELL
=> nothing

$ SHELL=/bin/bash posh -l
$ echo $SHELL
/bin/bash
=> ok
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC=C:\Windows\system32\cmd.exe
export SHELL=/bin/bash

PS : you're right, posh is broken regarding /etc/profile, etc. w/ -l !

== mksh ==

$ mksh -l
$ echo $SHELL
=> no default !
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC='C:\Windows\system32\cmd.exe'
export SHELL
=> empty !
$ env | grep SHELL
=> nothing

$ SHELL=/bin/bash mksh -l
$ echo $SHELL
/bin/bash
=> ok
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC='C:\Windows\system32\cmd.exe'
export SHELL=/bin/bash

== dash ==

same as mksh

== zsh ==

$ zsh -l
$ echo $SHELL
/bin/zsh
=> defaulted to /bin/zsh through /etc/profile.d/zshell.zsh
$ export | egrep 'SHELL|COMSPEC'
COMSPEC='C:\Windows\system32\cmd.exe'
SHELL=/bin/zsh

$ SHELL=/bin/bash zsh -l
$ echo $SHELL
/bin/bash
=> ok
$ export | egrep 'SHELL|COMSPEC'
COMSPEC='C:\Windows\system32\cmd.exe'
SHELL=/bin/bash

== ksh93 ==

$ ksh93 -l
$ echo $SHELL
/bin/sh
=> defaulted to /bin/sh instead of /path/to/ksh93 !
$ export | egrep 'SHELL|COMSPEC'
COMSPEC='C:\Windows\system32\cmd.exe'
=> no env SHELL

$ SHELL=/bin/bash ksh93 -l
$ echo $SHELL
/bin/bash
=> ok
$ export -p | egrep 'SHELL|COMSPEC'
export COMSPEC='C:\Windows\system32\cmd.exe'
export SHELL=/bin/bash

== csh/tcsh ==

$ csh -l
$ echo $SHELL
/bin/tcsh
=> defaulted to /bin/tcsh instead of /bin/csh through /etc/csh.login
$ printenv | egrep 'SHELL|COMSPEC'
COMSPEC=C:\Windows\system32\cmd.exe
SHELL=/bin/tcsh

$ SHELL=/bin/bash csh -l
$ echo $SHELL
/bin/tcsh
=> ko, $SHELL shouldn't be set irreparably in /etc/csh.login
if ( ! ${?SHELL} ) then
   setenv SHELL $shell
endif

so, export SHELL could be added to /etc/profile, isn't it ?

also, about mksh vs pdksh :
case $KSH_VERSION in *MIR*) SHELL=/bin/mksh ;; *) SHELL=/bin/ksh ;; esac

PS : mail from 31/03/2011, but it may not rich you ?

profile_d shouldn't set LC_COLLATE irreparably and should unset file :

would it be possible to change :

profile_d ()
{
   saved_LC_COLLATE=${LC_COLLATE}
   LC_COLLATE=C
   for file in /etc/profile.d/*.$1; do
     [ -e "${file}" ] && . "${file}"
   done
   LC_COLLATE=${saved_LC_COLLATE}
   unset saved_LC_COLLATE
}

to :

profile_d ()
{
   for file in $(export LC_COLLATE=C; echo /etc/profile.d/*.$1); do
     [ -e "${file}" ] && . "${file}"
   done
   unset file
}

PS1 *must not* be exported.

historically, it is not exported to know if it is a shell is interactive 
or not since only interactive shells set it.

i.e., the following both solutions are equivalent.

case $- in *i*) interactive ;; esac
[ -n $PS1 ] && interactive

if PS1 is exported, it is always set for subshells and this may cause 
trouble in some script.

also, from man bash :

An  interactive  shell  is one started without non-option arguments and
without the -c option whose standard input and error are both connected
to  terminals  (as determined by isatty(3)), or one started with the -i
option.  PS1 is set and $- includes i if bash is interactive,  allowing
a shell script or a startup file to test this state.

well, you answer me about that :

 >> What the man page doesn't tell you is that bash actually unsets PS1 
if the
 >> shell isn't interactive, so for bash at least, exporting PS1 can't 
cause a
 >> problem.

then, I reply :

 > thanks for the tip, however, this is not an expected behaviour...

also, what about other shells ? exporting PS1 broke this behavious.

PS again : english  isn't my natural language, so, forgive me if I'm too 
rough :-)

Regards,

Cyrille Lefevre
-- 
mailto:Cyrille.Lefevre-lists@laposte.net


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list