Search code examples
shellcygwinbashxterm

Can I Force XTerm.exe's Default BASH Shell and Other Non-Login Shells in Cygwin to Load ~/.bashrc?


I'm having a problem with Cygwin, specific to XTerm.exe sessions not loading BASH configuration file(s) properly.

For starters, my .startxwinrc is:

#!/bin/sh

xrdb -merge ~/.Xresources
xterm -geometry +0+60 -ls &
xterm -geometry +0-100 &
exec  xclock

...and my .Xresources is:

Xft*antialias:          true
Xft*autohint:           true
XTerm*background:   white
XTerm*foreground:   black
XTerm*cursorColor:  orchid
XTerm*fullCursor: true
XTerm*reverseVideo: false
XTerm*geometry:   80x40
XTerm*scrollBar:    true
XTerm*rightScrollBar:   true
XTerm*scrollTtyOutput: off
XTerm*scrollKey: on
XTerm*reverseWrap: true
XTerm*saveLines:    10000
XTerm*faceName:     BitStream Vera Sans Mono
XTerm*faceSize:     12
XTerm*toolBar:      off
XTerm*VT100.Translations: #override\n\
        <Key>BackSpace: string(0x7F)\n\
        <Key>Delete: string("\033[3~")\n\
        <Key>Home: string("\033[1~")\n\
        <Key>End: string("\033[4~")\n\
        <KeyPress>Prior : scroll-back(1,page)\n\
        <KeyPress>Next : scroll-forw(1,page)

I start my X server as:

startxwin &

And I see the above configurations worked... I get two XTerm windows and a xclock (and the color and scroll, etc. are per my specifications).

But curiously the terminal prompt is not what I set it to in my ~/.bashrc configuration file.

At first I thought my issue was related to these questions:

Why is my .bashrc not read under cygwin?
Cygwin shell doesn't execute .bashrc

...which suggest the issue is that the actual configuration settings are loaded from ~/.profile or ~/.bash_profile, perhaps. But adding these did nothing.

To verify they weren't running I added a line like this to each of the three bash configuration files (.bashrc, .bash_profile, and .profile) in my home directory:

echo "**** EXECUTING /home/JasonMick/.bash_profile *****" | \
    tee -a /tmp/shell.log

The file is never written... so clearly these files are never touched.

Next I verified that there is no "HOME" variable in my Windows Environment Variables (which some suggested could be the source of such problems). There was no such variable, so I was okay in that regard.

Next I verified some basic things about the shell state using...

printf '%s\n' $SHELL $HOME $USER

The results for the XTerm are:

/bin/bash
/home/JasonMick
JasonMick

These results match identically to those of the same command executed in the non-X11 terminal mintty (which I typically use to launch startxwin). However when I open the new mintty the prompt is correct, per the settings in my home directory .bashrc file.

To be on the safe side, I searched for .profile, .bashrc, and .bash_profile files in /etc/. I found the following files:

/etc/profile
/etc/bash.bashrc
/etc/skel/.bashrc
/etc/skel/.bash_profile
/etc/defaults/etc/skel/.bashrc
/etc/defaults/etc/skel/.bash_profile
/etc/defaults/etc/bash.bashrc
/etc/defaults/etc/profile

I added prints to all of them.

In mintty I the /etc/shell.log file gets the following commands:

**** EXECUTING /etc/profile ****
**** EXECUTING /etc/bash.bashrc *****
**** EXECUTING /home/JasonMick/.bash_profile *****

...so it appears to be calling the /etc/ files, then finally calling the .bash_profile in my home directory, automatically, without any source calls from the /etc/ located configuration files.

Removing the log, I launch startxwin. Xterm opens, but the log file isn't there!

This implies that XTerm isn't touching ANY configuration file.. not in /etc/ not in ${HOME}!

The only difference I've found is that when calling echo $0 $- in mintty I get:

-bash himBH

...where as in XTerm I get:

bash himBH

According to the info at:

Difference between Login Shell and Non-Login Shell?
Why 'echo $0' gives different result for two different terminals?

My bash shell in the Xterm is an interactive (i flag in $-) non-login (no - at the front of $0) BASH shell, while my mintty is a iteractive, login BASH shell.

Okay. Based on the second link above I still expect my non-login interactive shells to load my ~/.bashrc. But again, as stated above it does not only not loading that file... they're not loading ANY bash configuration file as far as I can tell. None in ${HOME}... none in /etc/.

Any idea how to force the non-login shells in Cygwin (i.e. XTerm default shell session) to properly source ~/.bashrc or ~/.bash_profile?

Am I doing something wrong?


Solution

  • I've discovered that in Cygwin I can get the non-login shells to load their configuration settings by invoking export ENV=~/.bashrc in my .startxwinrc file. The new .startxwinrc file is:

    #!/bin/sh
    export ENV=~/.bashrc
    xrdb -merge ~/.Xresources
    xterm -geometry +0+60 -ls &
    xterm -geometry +0-100 &
    exec  xclock
    

    Bother xterm sessions and their children now correctly source my ~/.bashrc.

    @Gilles in the thread Difference between Login Shell and Non-Login Shell? states:

    "When you start a shell in a terminal in an existing session (screen, X terminal, Emacs terminal buffer, a shell inside another, …), you get an interactive, non-login shell. That shell might read a shell configuration file (~/.bashrc for bash invoked as bash, /etc/zshrc and ~/.zshrc for zsh, /etc/csh.cshrc and ~/.cshrc for csh, the file indicated by the ENV variable for POSIX/XSI-compliant shells such as dash, ksh, and bash when invoked as sh, $ENV if set and ~/.mkshrc for mksh, etc.)."

    When I first read that, the first clause seemed to suggest that ~/.bashrc is loaded automatically for non-login shells. While the second clause does state that the variable ENV can be defined to set the configuration file location for bash, the language of the first clause makes it unclear whether this is necessary always or just sometimes? Based on my findings, it's possible that "sometimes" is true for some platforms where the default GUI files include a call to export the ENV variable corresponding to the configuration file of the default shell.

    @ThomasDickey's linked solution to a related question helped me to reevaluate @Gilles answer cited above. However, his suggestion to change my XTerm calls to login shells is not something at this point I consider the best answer, as the only difference that was of concern to me was the inability to automatically load the shell configuration, which my fix remedies for non-login shells.

    There are differences in calls to uptime and certain other reporting calls as Difference between... states, but those aren't something I forsee being a concern for my use case. My deployment is a single user local deployment using Cygwin with no intent to accept incoming ssh calls to my machine. Hence there's not compelling reason I can find not to adopt the simpler one line fix which applies the proper configuration file via ${ENV} to all XTerms, rather than the somewhat more verbose fix of adding a flag to every XTerm call, telling it to launch its shell in login mode.