On Mon, Dec 31, 2001 at 12:04:39AM -0500, John P Verel <[EMAIL PROTECTED]> wrote:
[...]
| > Perhaps I'm missing something here. Aren't the path modifications in 
| > /etc/profile conditional? If they are already in the users path, they 
| > shouldn't be added again. That being the case, re-sourcing that file 
| > shouldn't affect your path.
[... and other shell init stuff earlier in the thread ...]

Last October I ranted a bit about the startup scripts in the "Is Red Hat
heading down the wrong road?" thread. They are inefficient and overdone
(being redone in the /etc/bashrc! Geez!) Just for your amusement I repost
that rant here, which details some of the things done wrong.

Cameron Simpson, DoD#743        [EMAIL PROTECTED]    http://www.zip.com.au/~cs/

             ----------------------------------------------

  Date: Sat, 13 Oct 2001 17:19:15 +1000
  From: Cameron Simpson <[EMAIL PROTECTED]>
  To: [EMAIL PROTECTED]
  Subject: Re: Is Red Hat heading down the wrong road?
  Message-ID: <[EMAIL PROTECTED]>
  References: <[EMAIL PROTECTED]> 
<[EMAIL PROTECTED]> <3BC62C27.29850.DD84C@localhost>
  In-Reply-To: <3BC62C27.29850.DD84C@localhost>; from [EMAIL PROTECTED] on Thu, Oct 
11, 2001 at 11:32:55PM +0200

  Me> There are things I dislike about the RedHat stuff. I'd like to fix a lot
  Me> of their shell scripts; some are a bit inept (they do a lot of "if ... |
  Me> grep ..." where a case statement would be much faster and easier to read
  Me> to boot) and their bash system startup files are a nightmare. Flatout
  Me> wrong. But we fix that in our post-install stuff anyway now we know.

  Rodolfo> Hey Cameron, you wanna elaborate on this? Love to learn something here.

  On Thu, Oct 11, 2001 at 11:32:55PM +0200, Leonard den Ottolander 
<[EMAIL PROTECTED]> wrote:
  |  Just my thought. Cameron, please share some of your insights with us.

  Ok, since I did a bit of a dummy spit. I had been putting this off until
  I had a vanilla redhat machine to hand, because our fix here is to
  simply truncate /etc/bashrc and /etc/zshenv. It's amazingly effective
  but mangles the evidence :-(

  //////////////////////

  The first remark was about so many of the redhat /etc/profile.d files
  and a few of the /etc/init.d file which say variants on this:

          if ! printenv PATH | grep -q $kdepath ; then

  (from /etc/profile.d/kde.sh) which is testing for the absense of $kdepath
  in $PATH.

  Firstly: "!" is a bashism - many other shells don't like it. Since these
  files (in /etc/profile.d) are sourced by ALL Bourne style shells these
  dialect specific things _must_ be avoided or things will break.

  Secondly, you'll note that "!" here depends upon being the same level of
  precedence as the "if" word itself: is applies to the entire command list
  (which pipe-as-a-whole). Ugly, since this violates how damn near every
  other command works. It just mucks with one's mental model of the shell.

  Thirdly, this is very inefficient. It requires a pipe and two
  subprocesses, thus two forks and one exec(). And also a lot of waiting
  around while first the echo runs and quits, and then the grep runs
  and quits.

  Consider instead:

          case ":$PATH:" in
              *:"$kdepath":*)   ;;      # already present
              *)                                # missing
                                          ... do stuff here ...
                                          ;;
          esac

  No forks, no execs, no waiting. And depending on your indenting style, just
  as readable if not more so.

  BTW, that :$PATH: isn't some little known weird shell syntax, it's
  just the $PATH with colons either side so that the pattern match on
  *:$kdepath:* will work even if $kdepath is right at the front or back
  of $PATH.

  //////////////////////

  But the above merely annoys me for being a bit inept.

  What really really pisses me off is /etc/bashrc. Come, let us read:

      # are we an interactive shell?
      if [ "$PS1" ]; then

  Not even one line into the code it begins! Clue: testing $PS1 is _not_ a test for
  an interactive shell! You look at $- for that, and look for an "i", thus:

          case $- in *i*) # yes I'm interactive

  Testing $PS1 is totally dependent on having a pure and untrammelled RedHat
  vanilla install. Anyone may have set PS1 arbitrarily earlier. Or unset
  it! (Certainly here this test started breaking almost immediately for
  us.) What I think their idea was was that the user only gets $PS1 from
  /etc/profile or something like that.  But no such thing is true. Perhaps
  it is set _only_ in the .bashrc? After all the thing's only of use in an
  interactive context. Or perhaps they were thinking that a noninteractive
  shell won't have $PS1. But plenty of people set it and export it, and
  may also put it in places like ~/.ssh/environment so that it's there
  for any shell they invoke through ssh or such.

  Anyway, basicly false whatever their logic was. They should be testing $-.
  But also, /etc/bashrc is, IIRC, _only_ sourced by interactive shells anyway.
  So you don't need to do the test at all!

  Back to the bashrc:

          if [ -x /usr/bin/tput ]; then
            if [ "x`tput kbs`" != "x" ]; then # We can't do this with "dumb" terminal

  This is a bit weird. Testing for an absolute path (which, admittedly,
  is the only thing they can test) then not using that path explicitly
  when they run tput. Suppose the $PATH is different? Doesn't have
  /usr/bin maybe?  I'm just niggling here.

              stty erase `tput kbs`
            elif [ -x /usr/bin/wc ]; then
              if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" 
terminal
                stty erase `tput kbs`
              fi
            fi
          fi

  This is more weird. Firstly, this is inefficient. They seem to be seeing
  if "tput kbs" outputs anything, and then using it if so. But that runs
  tput twice. Secondly, they should be quoting the output of the tput in
  the "stty" line - after all the whole point of using tput is that we
  don't know what the preferred erase char is here, so it could be _anything_.
  Just niggling that one. Thirdly, the second tput test:

              if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" 
terminal

  appears to be doing exactly what the first one did. Why twice?
  Possible alternative code:

          if [ -x /usr/bin/tput ]; then
            kbs=`tput kbs`
            [ -n "$kbs" ] && stty erase "$kbs"
          fi

  Shorter, faster, robust, and easier to read.

  Now let us skip to the code which truly offends:

          if [ "x$SHLVL" != "x1" ]; then # We're not a login shell
              for i in /etc/profile.d/*.sh; do
                  if [ -x $i ]; then
                      . $i
                  fi
              done
          fi

  Leaving aside the $SHLVL test which I think is correct for what it's doing,
  WE ALREADY DID THIS STUFF! In /etc/profile! We SHOULD NOT be doing it again!
  Gross gross waste of time and cycles!

  There are two reasons I can imagine this code exists:

  - maybe some of those scripts make aliases or shell functions: unexported
    pershell thingies. Well frankly, that should be in a separate file, eg
    /etc/shellrc.d/whatever.

  - my prime suspect is the GUI login

  Let me elaborate on that, because it's a major difficulty that every X11
  GUI login presents, which can be worked around properly but is usually
  worked around very badly, like the above code.

  In the GUI logins, /etc/profile is generally not run by the support script
  which fires up the rest of the session in vanilla installs. This is, in my
  well known to really very humble opinion, a bad thing.

  The upshort is that new ternimals must either be login terminals,
  incurring a startup cost for every new window (ick - windows should
  be cheap cheap cheap!), or be plain shells which lack all that handy
  environment that /etc/profile should have set up. Often they are plain
  shells, and people naively source /etc/profile (or its guts in some less
  centralised and maintained form - you should see the horrors in many ASIC
  engineers' .cshrc files), basicly making them as expensive to invoke as
  login shells without the redeemiing features.

  Why the difference and the consequent ugly hacks?

  A "normal" console login runs a login shell, pure and simple: it sources
  /etc/profile and ~/.profile (or ~/.bash_profile) and so the command
  environment you expect is set up.

  If you then start an X11 session with startx or xinit, it then runs your
  .xinitrc (or the system default if you haven't got one), and because
  this all descends from your login shell everything run therein has the
  normal environment.

  With the advent of the GUI login via XDM this scheme goes out the window
  to some extent. Firstly, they generally don't source /etc/profile during
  their startup by default. Secondly, because some people don't have Bourne
  shells you can't just source /etc/profile and ~/.profile naively - they
  may not be appropriate. (This isn't an issue with a console login because
  the shell itself takes care of this in login mode; under the GUI we're
  trying to address this from a script). Thirdly, many ~/.profile files (and
  a few naively coded system /etc/profile files) imagine they're talking to
  an interactive terminal and do interactive things, like ask questions of
  the user. So even in general they can't blithely source the right things.

  So in general, the GUI doesn't even try. Because of this, unless the
  user has done something special themselves the environment the user's
  GUI clients run under is vanilla and spartan. Ugly!

  So what happens? Instead of biting the bullet like a fascist sysadmin
  would and writing a script to source the right things for whatever shell
  the user has and living with users shooting themselves in the foot
  if their startups do interactive things, we find code like the above
  in the /etc/bashrc or wherever which says "oh just go and do all this
  work anyway".

  Now, most GUI logins provide a hook of some kind for sourcing an arbitrary
  script at startup, prior to running the desktop stuff. For example,
  CDE sources ~/.dtprofile if it exists. So you can put:

          . /etc/profile
          . $HOME/.profile

  in that if you like. The GNOME and KDE desktops, I believe, have similar
  hooks. If you care, I yabber about this a bit over here:

          http://www.zip.com.au/~cs/answers/x11-one-size-fits-all.txt

  In short, rather than polluting the /etc/bashrc with gratuitous stuff
  which should have happened at login (i.e. at desktop startup time), it
  is far far better to source /etc/profile et al during the desktop startup
  and leave the bashrc streamlined. (For example, ours is empty here!)

  ///////////////////////

  So the main point of my rant here is that /etc/profile et al should be
  run ONCE and ONCE ONLY in any given login session, GUI or otherwise. The
  redhat stuff does not aim for this, and makes your machine seem slower
  than it needs to be. It also means that if you've made yourself a nice
  uncluttered $PATH and so forth for whatever reason, the /etc/bashrc will
  go and crud it up again for you!

  The only thing of any use in the existing /etc/bashrc is the tput thing, and
  personally I don't do that either. "stty erase ^h" does me fine.

  Well, that's my ranting done for now. Cheers,
  --
  Cameron Simpson, DoD#743        [EMAIL PROTECTED]    http://www.zip.com.au/~cs/

  Since we invented the mouse, the GUI, the laser printer, ...
  - _AppleNews_ August 1999



_______________________________________________
Redhat-list mailing list
[EMAIL PROTECTED]
https://listman.redhat.com/mailman/listinfo/redhat-list

Reply via email to