# SccsId[] = "%W% (USL function) %G%"
              EM_name="EMAIL_MSG"
              if [ ".${SECONDS}" = "." ]; then # Bourne function already loaded?
                 [ ."`set|egrep '^$EM_name\(\)\{$'`" != . ] && EM_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 '/^'$EM_name'[=\(]?/'`" != . ] && EM_loaded=1
                 else # Linux
                    [ ."`typeset -F|awk '/^'$EM_name'[=\(]?/'`" != . ] && EM_loaded=1
                 fi
              fi
              if [ 0${EM_loaded} -eq 0 ]; then
              #----------------------------------------------------------------------#
              EMAIL_MSG() # 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

                #------------------------------------#
                # Try to use mailx except on Linux.  #
                #------------------------------------#
                OZ=`uname -s 2> /dev/null|tr '[A-Z]' '[a-z]' 2> /dev/null`
                [ ."$OZ" = ."linux" ] && MAIL=/bin/mail || MAIL=/usr/bin/mailx

                . $SHLIB/exit.sh # Function dependencies

                #------------------------------------------------------------#
                # 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`}
                : ${host:=`hostname`}
                : ${script_name:=`basename $0`}
                : ${yymmddhhmiss:=`date '+%y''%m%d%H''%M''%S'`}
                : ${Xtimestamp:=`echo "obase=16;$yymmddhhmiss+$$"|bc`}
                : ${name_root:=`echo $script_name|$AWK '{sub(/^\.+/,"");sub(/\..*/,"");print}'`}
                : ${notify:=$LOGNAME@`uname -n`}
                : ${tmp:=/var/tmp}
                : ${sp:="                    "}
                : ${true:=1}
                : ${false:=0}
                : ${success:=0}
                : ${failure:=1}
                if [ ."${log}" = . ]; then
                   log=$tmp/$name_root"_log."$Xtimestamp
                   [ ."${teelog}" = . ] && teelog="cat"
                fi

                EM_ID="$script_name($EM_name)"

                #--------------------------------------------------------------------#
                # Attempting to generate a unique timestamps for $mailmsg and msgtxt.#
                #--------------------------------------------------------------------#
                EM_timestamp=$$"_"`date '+%Y''%m%d%H''%M''%S'`
                EM_random=`$AWK 'BEGIN {
                                         srand()
                                         random=rand()
                                         sub(/^0\./,"",random)
                                         print random
                                       }'`
                EM_mailmsg_root=$tmp/$name_root"_m"$EM_random"_"$id_hex"."
                EM_mailmsg=${EM_mailmsg_root}$Xtimestamp

                sleep 1 # Wait a second before getting the next random number.

                EM_timestamp=$$"_"`date '+%Y''%m%d%H''%M''%S'`
                EM_random=`$AWK 'BEGIN {
                                         srand()
                                         random=rand()
                                         sub(/^0\./,"",random)
                                         print random
                                       }'`
                EM_msgtxt_root=$tmp/$name_root"_mtxt"$EM_random"_"$id_hex"."
                EM_msgtxt=${EM_msgtxt_root}$Xtimestamp
                EM_teemsg="tee -ai $EM_msgtxt"

                #--------------------------------#
                # Parse this function's options. #
                #--------------------------------#
                EM_always_mail=0
                EM_arg_words=`   echo $1|wc -w`
                EM_arg_1st_char=`echo $1|cut -c1`
                #--------------------------------------------------------------#
                # If the number of words in $1 equals one and that word begins #
                # with a hyphen, then parse the dog as our own option list.    #
                #--------------------------------------------------------------#
                if [ $EM_arg_words -eq 1 -a ."$EM_arg_1st_char" = .'-' ]; then
                   EM_root=$tmp/$name_root"_EM_go_"$id_hex
                   EM_err=$EM_root"."$Xtimestamp
                   while getopts m EM_option 2>> $EM_err
                   do
                      case $EM_option in
                         m ) EM_always_mail=1
                             ;;
                        \? ) echo "$EM_ID" \
                               "Invalid option: -`sed 's/^.*-- //' $EM_err`" 1>&2
                             ;;
                         * ) ;;
                      esac
                   done
                   shift `expr $OPTIND - 1` # Shift past options to remaining args

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

                   [ ."${EM_root}" != . ] && \rm -f $EM_root* > /dev/null 2>&1
                fi

                #------------------------------------#
                # Showem basic command usage/syntax. #
                #------------------------------------#
                if [ $# -lt 1 ]; then
                   echo "`date '+%Y-%m-%d %T'`" \
                        "FATAL ERROR (Function): $host:$EM_ID"             1>&2
                   echo "${sp}Insufficient args."                          1>&2
                   echo "${sp}Usage: $EM_name [-m] 'subj' 'text line' ..." 1>&2
                   echo "${sp}          -m  Always notify by mail."        1>&2
                   echo "${sp}$script_name terminated."                    1>&2
                   [ ."${EM_mailmsg_root}" != . ] && \rm -f $EM_mailmsg_root* >/dev/null 2>&1
                   [ ."${EM_msgtxt_root}"  != . ] && \rm -f $EM_msgtxt_root*  >/dev/null 2>&1
                   EXIT 1
                fi

                #----------------------------------------------------------#
                # If we can't touch even $log or our work files, then spew #
                # everything out (this error and mail message) via stderr. #
                #----------------------------------------------------------#
                for EM_file in $log $EM_msgtxt $EM_mailmsg
                do
                   EM_stderr=`touch -- "$EM_file" 2>&1`
                   EM_status=$?
                   if [ $EM_status -ne 0 ]; then
                      echo "`date '+%Y-%m-%d %T'` FATAL ERROR: $EM_ID" 1>&2
                      echo "${sp}Unable to 'touch' \"$EM_file\"."      1>&2
                      echo "${sp}ERROR=$EM_stderr"                     1>&2
                      echo "${sp}mail message is as follows:"          1>&2
                      echo "${sp}$dashes"                              1>&2
                      for EM_arg
                      do
                         EM_ECHO_MSG "$EM_arg"                         1>&2
                      done
                      echo "${sp}$dashes"                              1>&2
                      echo "${sp}$script_name terminated."             1>&2

                      [ ."${EM_mailmsg_root}" != . ] \
                        && \rm -f $EM_mailmsg_root* >/dev/null 2>&1

                      [ ."${EM_msgtxt_root}"  != . ] \
                        && \rm -f $EM_msgtxt_root*  >/dev/null 2>&1
                      EXIT 1
                   fi
                done

                #------------------------------------------------------------------#
                # Save the $teelog variable because the user may specify "NO_LOG"  #
                # as an argument to this function (meaning that he doesn't want    #
                # what's being mailed to be placed in $log, perhaps redundantly.   #
                # (If we change teelog here, we'll restore it before returning.)   #
                #------------------------------------------------------------------#
                EM_saved_teelog="$teelog"

                EM_subject="`uname -n` $1"               # Assign $1 to subject,
                EM_dated_subj="`date '+%Y-%m-%d %T'` $1" # assign dated subject,
                echo "$EM_dated_subj" | $teelog          # display and log it,
                shift                                    # then shift past $1.

                #------------------------------------------------------------------#
                # Remove duplicate recipients and assign $emailee to $EM_to_whom.  #
                #------------------------------------------------------------------#
                 EM_to_whom=`echo $notify | sed "s/  */ /g" | tr " " "\012" \
                  | sort | uniq | tr "\012" " "`

                #----------------------------------------------------------------#
                # If, for whatever reason, we have no mail recipients, then spit #
                # out an error, BUT continue processing (the given notice will   #
                # still be written to the log).                                  #
                #----------------------------------------------------------------#
                if [ `echo $EM_to_whom|wc -w` -eq 0 ]; then
                   echo "`date '+%Y-%m-%d %T'` ERROR $EM_ID" | $teelog 1>&2
                   echo "${sp}Mail recipients missing."      \
                     "Notification impossible."              | $teelog 1>&2
                   echo "${sp}Logging is our only option."   \
                     "Processing continues."                 | $teelog 1>&2
                   EM_mail_ready=$false
                else
                   EM_mail_ready=$true
                fi

                #--------------------------------------------------------------------#
                # If running from cron (."$TERM" = .), or user specifically requests #
                # mail (calling this function with the -m option), AND (see the -a   #
                # [and] option in our test) we have mail recipients, then notify via #
                # mail. Else, notification is performed simply in logging the output.#
                #--------------------------------------------------------------------#
                if [ \( ."${TERM}" = . -o $EM_always_mail -eq 1 \) \
                     -a $EM_mail_ready = $true ]; then
                   #-------------------------------------------------------------#
                   # We're using mail to communicate.  Make sure that we have    #
                   # write permissions for $EM_msgtxt by zeroing it, changing    #
                   # its mode and testing the status of each of those operations.#
                   # If any problems doing that, then fuss at the user and exit. #
                   #-------------------------------------------------------------#
                   cp /dev/null $EM_msgtxt 2>&1
                   EM_status=$?
                   EM_stderr=`chmod 640 $EM_msgtxt`
                   EM_status=`expr $EM_status + $?`
                   if [ $EM_status -ne 0 ]; then
                      /bin/echo "`date '+%Y-%m-%d %T'`"                     \
                        "FATAL ERROR: $EM_ID"                               \
                        "\n${sp}Problem opening $EM_msgtxt. Error follows:" \
                        "\n${sp}ERROR=$EM_stderr"                           \
                        "\n${sp}$dashes"                                    \
                        "\n${sp}Mail (message text) follows:"               \
                        "\n${sp}$dashes" | $teelog 1>&2
                      #------------------------------------------------------#
                      # Before exiting, echo the mail message via stderr.    #
                      # ($log is fine--that's why we can still use $teelog-- #
                      # we just can't open $EM_msgtxt.)                      #
                      #------------------------------------------------------#
                      for EM_arg
                      do
                         EM_ECHO_MSG "$EM_arg"             | $teelog 1>&2
                      done
                      echo "${sp}$dashes"                  | $teelog 1>&2
                      echo "${sp}$script_name terminated." | $teelog 1>&2

                      [ ."${EM_mailmsg_root}" != . ] \
                        && \rm -f $EM_mailmsg_root* >/dev/null 2>&1

                      [ ."${EM_msgtxt_root}"  != . ] \
                        && \rm -f $EM_msgtxt_root*  >/dev/null 2>&1
                      EXIT $failure
                   fi

                   #-----------------------------------------------------------#
                   # OK, $EM_msgtxt looks OK.  Loop thru each arg, displaying  #
                   # each one (each arg is often several words) for the log    #
                   # and simultaneously writing it to the mail file.           #
                   #-----------------------------------------------------------#
                   [ ."${TERM}" = . ] && echo "$EM_dated_subj" 2>&1 >> $EM_msgtxt
                   for EM_arg
                   do
                      if [ ."${EM_arg}" = ."NO_LOG" ]; then
                         teelog=cat # We'll restore this before returning/exiting.
                         continue   # Iterate the loop (get the next string).
                      fi
                      EM_ECHO_MSG "$EM_arg" 2>&1 | $teelog | $EM_teemsg
                   done

                   #-------------------------------------------------------------#
                   # If $teelog was changed, then restore it to original setting.#
                   #-------------------------------------------------------------#
                    [ ."${teelog}" = ."cat" -o ."${teelog}" = ."sed" ] \
                      && teelog="$EM_saved_teelog"

                   #-----------------------------------------------#
                   # Do we strip leading spaces from mailed text?  #
                   #-----------------------------------------------#
                   $AWK -v sp="^$sp"               \
                        -v stdout_sp="^$stdout_sp" \
                        -v stderr_sp="^$stderr_sp" \
                   '{
                      sub(sp       ,       "")
                      sub(stdout_sp,"STDOUT=")
                      sub(stderr_sp,"STDERR=")
                      print
                    }' $EM_msgtxt > $EM_mailmsg

                   echo "`date '+%Y-%m-%d %T'`" \
                             "$MAIL -s'$EM_subject' $EM_to_whom < $EM_mailmsg" | $teelog
                   EM_stderr=`$MAIL -s"$EM_subject" $EM_to_whom < $EM_mailmsg 1>&2`
                   EM_status=$?
                   teelog="$EM_saved_teelog"      # Restore teelog to original
                   if [ $EM_status -ne 0 ]; then
                      /bin/echo "`date '+%Y-%m-%d %T'`"            \
                        "ERROR: $EM_ID"                            \
                        "\n${sp}$MAIL failure.  Status=$EM_status" \
                        "\n${sp}Error follows:"                    \
                        "\n${sp}ERROR=$EM_stderr"                  \
                        "\n${sp}$dashes"                           \
                        "\n${sp}Mail (message text) follows:" | $teelog 1>&2
                      #----------------------------------------#
                      # Put $EM_msgtxt out to stderr and hope  #
                      # it's not redirected to /dev/null.      #
                      echo "$EM_subject" 1>&2 # These have already been tee'd
                      cat   $EM_msgtxt   1>&2 # to $log (above)
                      #----------------------------------------#
                   fi
                else # Running interactively, use echo instead of mail.
                   for EM_arg
                   do
                      if [ "$EM_arg" = "NO_LOG" ]; then
                         teelog=cat # We'll restore this before returning/exiting.
                         continue   # Iterate the loop (get the next string).
                      fi
                      EM_ECHO_MSG "$EM_arg" 2>&1 | $teelog
                   done
                   #-------------------------------------------------------------#
                   # If $teelog was changed, then restore it to original setting.#
                   #-------------------------------------------------------------#
                   [ ."${teelog}" = ."cat" -o ."${teelog}" = ."sed" ] \
                     && teelog="$EM_saved_teelog"
                fi

                [ ."${EM_mailmsg_root}" != . ] && \rm -f $EM_mailmsg_root* >/dev/null 2>&1
                [ ."${EM_msgtxt_root}"  != . ] && \rm -f $EM_msgtxt_root*  >/dev/null 2>&1

                [ $EM_status   -ne  0 ] && EXIT 1 || return 0
              }  # "EM_" prefix identifies this function's variables.


              #======================================================================#
              EEM_name="EM_ECHO_MSG"                                                 #
              #----------------------------------------------------------------------#
              EM_ECHO_MSG() # $* = quoted strings for echoing.                       #
              #----------------------------------------------------------------------#
              { [ ."${AWK}" = . ] && { { [ -x /usr/bin/nawk ] && AWK=/usr/bin/nawk; } \
                                  ||   { [ -x /bin/gawk     ] && AWK=/bin/gawk    ; } \
                                  ||   { [ -x /usr/bin/awk  ] && AWK=/usr/bin/awk ; }; }

                [ $# -eq 0 ] && return 1 # Back to you if you forget the argstring.
                : ${host:=`hostname`}

                EEM_ID="$host:$script_name($EEM_name)"
                #----------------------------------------------------------#
                # If 1st five chars of $arg is not "FILE=" then process it #
                # normally.  Else, the user is telling us that we're to    #
                # process the file whose name immediately follows "FILE="  #
                # (we do the same thing below in interactive processing).  #
                #----------------------------------------------------------#
                EEM_char1_5=`echo "$*"|$AWK '{print substr($1,1,5); exit}'`
                if [ ."${EEM_char1_5}" != ."FILE=" ]; then # No file here.
                   #-----------------------------------------------#
                   # /bin/echo is used because argstring may have  #
                   # control characters (e.g. \c) imbedded within. #
                   #-----------------------------------------------#
                   /bin/echo "$*"
                else  # It's supposed to be a file, get the fileid.
                   EEM_text_file=`echo "$*" \
                    | $AWK '{gsub(/^[\t\n\r ]*FILE=/,"");print;exit}'`
                   #-----------------------------------------------------------#
                   # If "FILE=" is specified, but the user forgets to pass us  #
                   # the fileid, then fuss at em, but continue.  If the fileid #
                   # turns out to be an empty file, then make note it and      #
                   # continue.  Otherwise, all's well, so print the dog.       #
                   #-----------------------------------------------------------#
                   if [ ."${EEM_text_file}" = . ]; then
                      echo "`date '+%Y-%m-%d %T'` ERROR: $EEM_ID\n"       1>&2
                      echo "${sp}'FILE=' specified, but no fileid given!" 1>&2
                   elif [ ! -s $EEM_text_file ]; then
                      echo "${sp}FILE=$EEM_text_file (zero length)."
                   else
                      cat $EEM_text_file
                   fi
                fi
              }  # "EEM_" prefix identifies this function's variables.
              fi

              #======================================================================#
              #                       D O C U M E N T A T I O N                      #
              #======================================================================#
              #                                                                      #
              #      Author: Bob Orlando                                             #
              #                                                                      #
              #        Date: December 14, 1996 (Bob@OrlandoKuntao.com)               #
              #                                                                      #
              #  Program ID: email_msg.sh                                            #
              #                                                                      #
              #       Usage: EMAIL_MSG [-m] "subject" "text line" ...                #
              #                         -m   Always notify by mail.                  #
              #                                                                      #
              #     Purpose: Email subject and message text supplied as arguments    #
              #              to recipients previously assigned to $notify.           #
              #                                                                      #
              #     Globals: No global variables assigned from this function.        #
              #             "EM_" prefix identifies local function variables.        #
              #                                                                      #
              # Exit_status: Exits with failure (1) for fatal error (e.g. user       #
              #              supplies an invalid argument, or mailx fails).          #
              #              Otherwise returns success (0).                          #
              #                                                                      #
              #       Calls: EXIT library functions and EM_ECHO_MSG local/sub-       #
              #              function (See Notes: below).                            #
              #                                                                      #
              #       Files: Temporary work files, $EM_mailmsg and $EM_msgtxt        #
              #              are removed prior to exiting.                           #
              #                                                                      #
              #       Notes: Text line (each line within quotes) may optionally be   #
              #              the keywords "NO_LOG" or "FILE=".  NO_LOG means that    #
              #              the text that follows is not to be placed in $log.      #
              #              FILE= means we take the fileid that follows as our      #
              #              text input.                                             #
              #                                                                      #
              #              Included with this function, is a second function:      #
              #              EM_ECHO_MSG.  Using this function prevents duplicating  #
              #              code (since it is called in four places).               #
              #                                                                      #
              #              If this function is run interactively, no mail notice   #
              #              is sent to $notify.  This is because, the letter        #
              #              is being displayed at the terminal.  Only in batch      #
              #              mode (e.g. cron) is mail used.                          #
              #                                                                      #
              #    Modified: 2004-04-02 Bob Orlando                                  #
              #                 v1.14 * Expand $AWK testing and assignment.          #
              #                       * Change $USER to $LOGNAME.                    #
              #                                                                      #
              #----------------------------------------------------------------------#
            
Artificial Intelligence is no match for natural stupidity.
©Copyright Bob Orlando, 1996-2011
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update: Jan. 26, 2011
by Bob Orlando