# SccsId[] = "%W% (USL function) %G%"
              EAR_name="EXIT_IF_ALREADY_RUNNING"
              if [ ".${SECONDS}" = "." ]; then # Bourne function already loaded?
                 [ ."`set|egrep '^$EAR_name\(\)\{$'`" != . ] && EAR_loaded=1
              else # Korn or Bash shell and function already loaded?
                 if [ `expr "\`uname -s\`" : "[Ll][Ii][Nn][Uu][Xx]"` -eq 0 ]; then
                    [ ."`typeset +f|awk '/^'$EAR_name'[=\(]?/'`" != . ] && EAR_loaded=1
                 else # Linux
                    [ ."`typeset -F|awk '/^'$EAR_name'[=\(]?/'`" != . ] && EAR_loaded=1
                 fi
              fi
              if [ 0${EAR_loaded} -eq 0 ]; then
              #----------------------------------------------------------------------#
              EXIT_IF_ALREADY_RUNNING() # Function documentation located at bottom.  #
              #----------------------------------------------------------------------#
              { [ ."${AWK}" = . ] && { { [ -x /usr/bin/nawk ] && AWK=/usr/bin/nawk; } \
                                  ||   { [ -x /bin/gawk     ] && AWK=/bin/gawk    ; } \
                                  ||   { [ -x /usr/bin/awk  ] && AWK=/usr/bin/awk ; }; }

                if [ .${SHLIB} = . ]; then SHLIB=/usr/local/scripts; export SHLIB; fi

                . $SHLIB/email_msg.sh            # Calls $SHLIB/exit.sh
                . $SHLIB/write_err_to_syslogs.sh

                #------------------------------------------------------------#
                # If the following variables are not set, use these defaults.#
                #------------------------------------------------------------#
                : ${id_num=`id|sed 's/^\(uid=\)\([0-9]*\)\(.*\)/\2/'`}
                : ${id_hex=`echo "obase=16;$id_num"|bc`}
                : ${script_name:=`basename $0`}
                : ${name_root:=`echo $script_name|$AWK '{sub(/^\.+/,"");sub(/\..*/,"");print}'`}
                : ${yymmddhhmiss:=`date '+%y''%m%d%H''%M''%S'`}
                : ${Xtimestamp:=`echo "obase=16;$yymmddhhmiss+$$"|bc`}
                : ${sp:="                    "}
                : ${tmp:=/var/tmp}
                : ${OZ:=`uname -s 2> /dev/null|tr '[A-Z]' '[a-z]' 2> /dev/null`}

                if [ ."$ps_opts" = . ]; then
                   if [ ."$OZ" != ."linux" ]; then
                      EAR_ps_opts="-f -u $id_num"
                   else
                      EAR_ps_opts='-aux'
                   fi
                fi

                if [ ."$log" = . ]; then
                   log=$name_root.log
                   [ ."$teelog" = . ] && teelog="cat"
                fi

                EAR_ID="$script_name($EAR_name)"

                #----------------------------#
                # Parse any function options.#
                #----------------------------#
                EAR_option=0
                EAR_opt_l=0
                EAR_opt_p=0
                EAR_opt_t=0
                EAR_pri="$logger_p" # $logger_p and $logger_t are assigned defaults
                EAR_tag="$logger_t" # within library defaults.sh.

                EAR_root=$tmp/$name_root"_EAR_go_"$id_hex
                EAR_err=$EAR_root"."$Xtimestamp
                while getopts lp:t: EAR_opt 2>> $EAR_err
                do
                   #-----------------------------------------------------------------#
                   # The EAR_option and EAR_opt_l are necessary to prevent possible  #
                   # command options (which must be specified after function         #
                   # options) from being confused with function options.             #
                   #-----------------------------------------------------------------#
                   case $EAR_opt in
                      l ) EAR_opt_l=1
                          EAR_option=1
                          ;;
                      p ) EAR_opt_p=1
                          EAR_pri="$OPTARG"
                          EAR_option=1
                          ;;
                      t ) EAR_opt_t=1
                          EAR_tag="$OPTARG"
                          EAR_option=1
                          ;;
                     \? ) echo "$EAR_ID" \
                            "Invalid option: -`sed 's/^.*-- //' $EAR_err`" 1>&2
                          ;;
                      * ) ;;
                   esac
                done
                [ $EAR_option -ne 0 ] && shift `expr $OPTIND - 1` # Shift past options to remaining args
                [ ."$EAR_root" != . ] && \rm -f $EAR_root* > /dev/null 2>&1

                #----------------------------------------------------------------#
                # Must reset this dog if this function is apt to be called again #
                OPTIND=1  # (try and find this fact documented anywhere else).   #
                #----------------------------------------------------------------#

                #----------------------------------------------------------------#
                # Awk script assumes variables 'sp' and 'pid' are passed to it.  #
                #----------------------------------------------------------------#
                EAR_awk_scr='BEGIN {n=0}
                             $2 == pid {
                                         gsub(/[\t ]+/, " ", $0)
                                         sub(/^[\t ]*/, sp,  $0)
                                         print
                                         n++
                                       }
                             END {exit n}'

                #----------------------------------------------------------------#
                EAR_CREATE_FILE() # Subfunction to create $active_status_file.   #
                #----------------------------------------------------------------#
                {                                                                #
                   echo "`date '+%Y-%m-%d %T'`" \
                     "echo $$ > $active_status_file" | $teelog
                      echo $$ > $active_status_file

                   if [ $? -eq 0 ]; then
                      chmod 0644 $active_status_file
                      return 0 # Ah, the sweet smell of success.
                   else
                      EAR_m1="Problem creating $active_status_file!"
                      EAR_m2="$script_name terminated."
                      EMAIL_MSG "FATAL ERROR (Function): $EAR_ID" \
                        "${sp}$EAR_m1"                            \
                        "${sp}$EAR_m2"
                      if [ $EAR_opt_l -eq 1 ]; then
                         WRITE_ERR_TO_SYSLOGS -p "$EAR_pri" -t "$EAR_tag" \
                           "BATCH $EAR_ID $EAR_m1 $EAR_m2"
                      fi
                      EXIT 1;
                   fi
                } # EAR_CREATE_FILE()                                            #
                #----------------------------------------------------------------#

                #------------------------------------------------------------#
                # If we still have arguments (optional/replacement message), #
                # then use that message, else use the default.               #
                #------------------------------------------------------------#
                [ $# -eq 0 ] && EAR_subj="NOTICE:" || EAR_subj=$*

                #--------------------------------------------------------------------#
                # If we have what looks like a good $active_status_file, then see    #
                # if the PID in that file is running (in the process queue).  If     #
                # it is in the process queue, then life is good.  However, if that   #
                # process is not running, then we take over those duties--beginning  #
                # by creating a new $active_status_file.                             #
                #--------------------------------------------------------------------#
                if [ ."$active_status_file" != . ]; then
                   if [ -s $active_status_file ]; then        # Non zero-length file
                      EAR_pid=`sed -n 1p $active_status_file` # Get PID from file
                      ps $EAR_ps_opts \
                       | $AWK -v pid=$EAR_pid -v sp="$sp" "$EAR_awk_scr" # No $teelog
                      if [ $? -gt 0 ]; then
                         EAR_m1="Cancelling $script_name ($$)."
                         EAR_m2="PID $EAR_pid already running."
                         EMAIL_MSG "$EAR_ID $EAR_subj"                           \
                           "${sp}$EAR_m1"                                        \
                           "${sp}Found active status file, $active_status_file." \
                           "${sp}$EAR_m2"
                         EXIT 1
                      else # Got an active status file, but process not running.
                         EMAIL_MSG "$EAR_ID $EAR_subj"                       \
                           "${sp}Active status file found, but $script_name" \
                           "${sp}(PID=$EAR_pid) NOT found in process queue." \
                           "${sp}Continuing $script_name."
                         EAR_CREATE_FILE
                         return 0 # All's well (it's our own PID)
                      fi
                   elif [ -f $active_status_file ]; then # File exists, but is empty.
                      EMAIL_MSG "$EAR_ID $EAR_subj"                                 \
                        "${sp}$EAR_m1"                                              \
                        "${sp}Found EMPTY active status file, $active_status_file." \
                        "${sp}$EAR_m2"
                      if [ $EAR_opt_l -eq 1 ]; then # Logger option? (1 = yes)
                         WRITE_ERR_TO_SYSLOGS -p "$EAR_pri" -t "$EAR_tag" \
                           "$EAR_ID $EAR_subj $EAR_m1 $EAR_m2"
                      fi
                      EXIT 1
                   else
                      EAR_CREATE_FILE

                      if [ $? -eq 0 ]; then
                         return 0 # Ah, the sweet smell of success.
                      else
                         EAR_m1="Problem creating $active_status_file!"
                         EAR_m2="$script_name terminated."
                         EMAIL_MSG "FATAL ERROR: $EAR_ID" \
                           "${sp}$EAR_m1"                 \
                           "${sp}$EAR_m2"
                         if [ $EAR_opt_l -eq 1 ]; then
                            WRITE_ERR_TO_SYSLOGS -p "$EAR_pri" -t "$EAR_tag" \
                              "BATCH $EAR_ID $EAR_m1 $EAR_m2"
                         fi
                         EXIT 1
                      fi
                   fi
                else
                   EAR_m1="active_status_file variable NOT assigned!"
                   EAR_m2="$script_name terminated."
                   EMAIL_MSG "FATAL ERROR: $EAR_ID" \
                     "${sp}$EAR_m1"                 \
                     "${sp}$EAR_m2"
                   if [ $EAR_opt_l -eq 1 ]; then
                      WRITE_ERR_TO_SYSLOGS -p "$EAR_pri" -t "$EAR_tag" \
                        "BATCH $EAR_ID $EAR_m1 $EAR_m2"
                   fi
                   EXIT 1
                fi
              } # "EAR_" prefix identifies this function's local variables.
              fi

              #======================================================================#
              #                       D O C U M E N T A T I O N                      #
              #======================================================================#
              #                                                                      #
              #      Author: Bob Orlando                                             #
              #                                                                      #
              #        Date: April 7, 1997                                           #
              #                                                                      #
              #  Program ID: exit_if_already_running.sh                              #
              #                                                                      #
              #       Usage: EXIT_IF_ALREADY_RUNNING [-l [-p priority] [-t tag]]     #
              #                                      [optional/replacement subject]  #
              #                                                                      #
              #                          -l = Notify via logger command              #
              #                               (default is false)                     #
              #                          -p = logger priority string                 #
              #                               (default is "user.err")                #
              #                          -t = logger tag string                      #
              #                               (default is "$LOGNAME[$$]")            #
              #                                                                      #
              #              Option notes: Option (-l) MUST precede -p and -t.       #
              #                                                                      #
              #     Purpose: Exit if the current process is already running.         #
              #                                                                      #
              # Description: If the script calling us is already running, then we    #
              #              don't start a new one, providing we find the process    #
              #              ID (held in the active status file) is actually in the  #
              #              process (ps) queue.  If the PID is not among 'ps'       #
              #              output, we report that fact, put our PID in the active  #
              #              status file, and continue.  If the process is indeed    #
              #              running, we notify responsible parties of its presence  #
              #              and exit (terminating the calling program).             #
              #                                                                      #
              #     Globals: Tests for presence of variable $active_status_file      #
              #              and the file to which it points.                        #
              #              "EAR_" prefix identifies local function variables.      #
              #                                                                      #
              #       Calls: EMAIL_MSG and EXIT library functions.                   #
              #              Optionally, WRITE_ERR_TO_SYSLOGS is also called.        #
              #                                                                      #
              # Exit_status: Success if no active status file exists and this        #
              #              function is able to create one.  Otherwise, we exit     #
              #              with nonzero status.                                    #
              #                                                                      #
              #       Notes: .....................................................   #
              #              .....................................................   #
              #                                                                      #
              #    Modified: 2004-04-02 Bob Orlando                                  #
              #                 v1.17 * Expand $AWK testing and assignment.          #
              #                                                                      #
              #              2004-03-03 Bob Orlando                                  #
              #                 v1.16 * Change set|egrep|awk to just set|egrep.      #
              #                                                                      #
              #----------------------------------------------------------------------#
            
Artificial Intelligence is no match for natural stupidity.
©Copyright Bob Orlando, 1997-2011
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update: Jan. 26, 2011
by Bob Orlando