47 Validating the User Environment

#47 Validating the User Environment

Because people migrate their login, profile, and other shell environment customizations from one system to another, it's not uncommon to have progressive decay in these settings. Eventually, the PATH can include directories that aren't on the system, the PAGER can point to a nonexistent binary, and worse .

A sophisticated solution to this problem is first to check the PATH to ensure that it includes only valid directories on the system, and then to check each of the key helper application settings to ensure that they're either indicating a fully qualified file that exists or that they are specifying a binary that's in the PATH .

The Code

 #!/bin/sh # validator - Checks to ensure that the PATH contains only valid directories, #   then checks that all environment variables are valid. #   Looks at SHELL, HOME, PATH, EDITOR, MAIL, and PAGER. errors=0 in_path() {   # Given a command and the PATH, try to find the command. Returns   # 1 if found, 0 if not.  Note that this temporarily modifies the   # IFS input field separator but restores it upon completion.   cmd=    path=    retval=0   oldIFS=$IFS; IFS=":"   for directory in $path   do     if [ -x $directory/$cmd ] ; then       retval=1      # if we're here, we found $cmd in $directory     fi   done   IFS=$oldIFS   return $retval } validate() {   varname=    varvalue=   if [ ! -z $varvalue ] ; then     if [ "${varvalue%${varvalue#?}}" = "/" ] ; then       if [ ! -x $varvalue ] ; then         echo "** $varname set to $varvalue, but I cannot find executable."         errors=$(( $errors + 1 ))       fi     else       if in_path $varvalue $PATH ; then         echo "** $varname set to $varvalue, but I cannot find it in PATH."         errors=$(( $errors + 1 ))       fi     fi   fi } ####### Beginning of actual shell script ####### if [ ! -x ${SHELL:?"Cannot proceed without SHELL being defined."} ] ; then   echo "** SHELL set to $SHELL, but I cannot find that executable."   errors=$(( $errors + 1 )) fi if [ ! -d ${HOME:?"You need to have your HOME set to your home directory"} ] then   echo "** HOME set to $HOME, but it's not a directory."   errors=$(( $errors + 1 )) fi # Our first interesting test: are all the paths in PATH valid? oldIFS=$IFS; IFS=":"     # IFS is the field separator. We'll change to ':' for directory in $PATH do   if [ ! -d $directory ] ; then       echo "** PATH contains invalid directory $directory"       errors=$(( $errors + 1 ))   fi done IFS=$oldIFS             # restore value for rest of script # The following variables should each be a fully qualified path, # but they may be either  undefined  or a progname. #   Add additional variables as necessary for # your site and user community. validate "EDITOR" $EDITOR validate "MAILER" $MAILER validate "PAGER"  $PAGER # And, finally, a different ending depending on whether errors > 0 if [ $errors -gt 0 ] ; then   echo "Errors encountered. Please notify sysadmin for help." else   echo "Your environment checks out fine." fi exit 0 

How It Works

The tests performed by this script aren't overly complex. To check that all the directories in PATH are valid, the code steps through each directory to ensure that it exists. Notice that the internal field separator (IFS) had to be changed to a colon so that the script would properly step through all of the PATH directories. By convention, the PATH variable uses a colon to separate each of its directories, as shown here:

 $  echo $PATH  /bin/:/sbin:/usr/bin:/sw/bin:/usr/X11R6/bin:/usr/local/mybin 

To validate that the environment variable values are valid, the validate() function first checks to see if each value begins with a /. If it does, the function checks to see if the variable is an executable. If it doesn't begin with a /, the script calls the in_path() function to see if the program is found in one of the directories in the current PATH .

The most unusual aspects of this script are its use of default values within some of the conditionals and its use of variable slicing. Its use of default values in the conditionals is exemplified by the following:

 if [ ! -x ${SHELL:?"Cannot proceed without SHELL being defined."} ] ; then 

The notation ${varname:?"errorMessage"} can be read as if varname exists, substitute its value; otherwise , fail with the error errorMessage .

The variable slicing notation, ${varvalue%${varvalue#?}} , is the POSIX sub-string function, producing only the first character of the variable varvalue . In this script, it's used to ascertain whether an environment variable has a fully qualified filename (one starting with / and specifying the path to the binary).

If your version of Unix/Linux doesn't support either of these notations, they can be replaced in a straightforward fashion. For example, instead of ${SHELL:?No Shell} you could substitute

 if [ -z $SHELL ] ; then   echo "No Shell" >&2; exit 1 fi 

And instead of {varvalue%${varvalue#?}} , you could use the following code to accomplish the same result:

 $(echo $varvalue  cut -c1) 

Running the Code

This is code that users can run to check their own environment. There are no starting arguments.

The Results

 $  validator  ** PATH contains invalid directory /usr/local/mybin ** MAILER set to /usr/local/bin/elm, but I cannot find executable. Errors encountered. Please notify sysadmin for help. 

Wicked Cool Shell Scripts. 101 Scripts for Linux, Mac OS X, and Unix Systems
Wicked Cool Shell Scripts
ISBN: 1593270127
EAN: 2147483647
Year: 2004
Pages: 150
Authors: Dave Taylor

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net