In addition to all the inline/code comments/documentation
140 lines of  formal documentation  are located at the bottom of this program.
                      #!/bin/sh
                      #
                      # SccsId[] = "%W% %G% (shell script)"
                      #
                      #----------------------------------------------------------------------#
                      #                             janitor.sh                               #
                      # -------------------------------------------------------------------- #
                      #   Program documentation and notes located at the bottom of script.   #
                      #----------------------------------------------------------------------#

                        #--------------------------------------------------------------#
                        # Assignments for name_root and script_name are necessary if   #
                        # there exists the possibility that this process may be run    #
                        # by the 'at' command. Run via 'at' and the `basename $0` used #
                        # in /usr/local/scripts/defaults.sh to assign $script_name,    #
                        # simply returns the name, 'sh' (hardly desirable).            #
                        #--------------------------------------------------------------#
                        name_root="janitor"
                        script_name=$name_root.sh
                        args=`echo "$@" | sed 's/-/\\-/g'` # Escape dashes
                        prelims="`date '+%Y-%m-%d %T'` $script_name (v%I%)" # SCCS keyword

                        #--------------------------------------------------------------#
                        # Make sure we can find all necessary commands and libraries.  #
                        #--------------------------------------------------------------#
                        PATH=/usr/bin:/sbin:/bin:/usr/sbin:/usr/ucb:$PATH; export PATH
                        LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/include:/usr/local/lib:/usr/lib:/lib
                        export LD_LIBRARY_PATH

                        program_start=`date '+%Y-%m-%d %T'`

                        #--------------------------------------------------------------#
                        # Use nawk or gawk, et al, depending on the OS.                #
                        #--------------------------------------------------------------#
                        OZ=`uname -s 2> /dev/null | tr '[A-Z]' '[a-z]' 2> /dev/null`
                        if [ ."$OZ" != ."linux" ]; then
                           bin_dir=/usr/bin
                           AWK=nawk
                           MAIL=$bin_dir/mailx
                           DF=$bin_dir/df
                           ECHO=$bin_dir/echo
                        else # Linux
                           bin_dir=/bin
                           AWK=gawk
                           MAIL=$bin_dir/mail
                           DF=$bin_dir/df
                           ECHO="$bin_dir/echo -e"
                        fi
                        df_opt="-lk"

                        rm=$bin_dir/rm
                        host=`hostname || uname -n`
                        HOST=`echo $host | $AWK '{sub(/\..*/,"");print toupper($0)}'`


                      #======================================================================#
                      #                 I N T E R N A L    F U N C T I O N S                 #
                      #----------------------------------------------------------------------#
                      MAIL_ERROR() # Requires $subject and $msg to be assigned.              #
                      #----------------------------------------------------------------------#
                      {
                        $ECHO "`date '+%Y-%m-%d %T'` $subject\n$msg" 1>&2
                        $ECHO "`date '+%Y-%m-%d %T'` $msg" \
                          | $MAIL -s "$subject" "Bob@OrlandoKuntao.com"
                      }


                      #======================================================================#
                      #                  L I B R A R Y    F U N C T I O N S                  #
                      #                       (in alphabetical order)                        #
                      #----------------------------------------------------------------------#
                        cwd=`pwd`

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

                        #----------------------------------------------------------------#
                        # If we can't get to shell library, call for help and exit.      #
                        #----------------------------------------------------------------#
                        `cd $SHLIB 2>&1`
                        status=$?
                        if [ $status -ne 0 ]; then
                           syslog_msg1="Problems cd'ng to $SHLIB."
                           syslog_msg2="Chdir status=$status.  $script_name ($$) terminated."

                           subject="FATAL ERROR $HOST: CD SHLIB Failure"
                           msg="$syslog_msg1\n$syslog_msg2"
                           MAIL_ERROR
                           exit 1
                        fi
                        cd $SHLIB 2>&1

                        #----------------------------------------------------------------#
                        # We do this first.  Set it up so that when we receive a signal  #
                        # (CTL-C, kill, whatever) we echo the signal we received and     #
                        # exit accordingly.  We expand this once we get into 'M A I N'.  #
                        # We skip some signals including CTL-Z and BG (for backgrounding #
                        # an interactive process).                                       #
                        #----------------------------------------------------------------#
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Assign signal traps."
                        n=0
                        for sig in `kill -l`
                        do
                           n=`expr $n + 1`
                           [    ".$sig" = ".EXIT" -o ".$sig" = ".SEGV" \
                             -o ".$sig" = ".CHLD" -o ".$sig" = ".CLD"  \
                             -o ".$sig" = ".TSTP" -o ".$sig" = ".CONT" \
                           ] && continue
                           trap "echo Exit $sig \($n\) 1>&2; exit $n" $n
                        done

                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Load library functions."
                        . ./chdir_exit_err.sh             ; status=$?
                        . ./chmod_exit_err.sh             ; status=`expr $status + $?`
                        . ./chmod_exit_err_nomail.sh      ; status=`expr $status + $?`
                        . ./chown_exit_err.sh             ; status=`expr $status + $?`
                        . ./cleanup_work_files.sh         ; status=`expr $status + $?`
                        . ./cp_dev_null_exit_err.sh       ; status=`expr $status + $?`
                        . ./cp_dev_null_exit_err_nomail.sh; status=`expr $status + $?`
                        . ./cp_exit_err.sh                ; status=`expr $status + $?`
                        . ./elapsed_time.sh               ; status=`expr $status + $?`
                        . ./email_msg.sh                  ; status=`expr $status + $?`
                        . ./exit.sh                       ; status=`expr $status + $?`
                        . ./exit_if_already_running.sh    ; status=`expr $status + $?`
                        . ./format_num_with_commas.sh     ; status=`expr $status + $?`
                        . ./get_file_perms.sh             ; status=`expr $status + $?`
                        . ./isint.sh                      ; status=`expr $status + $?`
                        . ./mv_exit_err.sh                ; status=`expr $status + $?`
                        . ./parse_parameters.sh           ; status=`expr $status + $?`
                        . ./print_vars.sh                 ; status=`expr $status + $?`
                        . ./prune_files.sh                ; status=`expr $status + $?`
                        . ./range_nums.sh                 ; status=`expr $status + $?`
                        . ./rm_exit_err.sh                ; status=`expr $status + $?`
                        . ./show_documentation.sh         ; status=`expr $status + $?`
                        . ./terminate.sh                  ; status=`expr $status + $?`
                        . ./terminate_subprocesses.sh     ; status=`expr $status + $?`
                        . ./touch_exit_err.sh             ; status=`expr $status + $?`
                        . ./touch_exit_err_nomail.sh      ; status=`expr $status + $?`
                        . ./trap_exit.sh                  ; status=`expr $status + $?`
                        . ./verify_num_vars.sh            ; status=`expr $status + $?`
                        . ./verify_vars.sh                ; status=`expr $status + $?`
                        # This one last.
                        . ./defaults.sh                   ; status=`expr $status + $?`

                        #--------------------------------------------------------------#
                        # If anything fails to load, fuss about it and exit.           #
                        #--------------------------------------------------------------#
                        if [ $status -ne 0 ]; then
                           syslog_msg1="Function load problems (status=$status)."
                           syslog_msg2="$script_name '$args' ($$) terminated."

                           subject="FATAL ERROR $HOST: SHLIB LOAD Failure"
                           msg="$syslog_msg1\n$syslog_msg2"
                           MAIL_ERROR
                           exit 1
                        fi
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Function load complete."

                        #--------------------------------------------------------------#
                        # Problems changing to $cwd?  Fuss about it and split.         #
                        #--------------------------------------------------------------#
                        `cd $cwd 2>&1`
                        status=$?
                        if [ $status -ne 0 ]; then
                           syslog_msg1="Problems cd'ng to $cwd!"
                           syslog_msg2="Chdir status=$status.  $script_name ($$) terminated."

                           subject="FATAL ERROR $HOST: SHLIB LOAD Failure"
                           msg="$syslog_msg1\n$syslog_msg2"
                           MAIL_ERROR
                           exit 1
                        fi
                        cd $cwd


                      #======================================================================#
                      #                     U S E R    F U N C T I O N S                     #
                      #                        (in alphabetical order)                       #
                      #----------------------------------------------------------------------#
                      BROKEN_SYMBOLIC_LINKS() # Global variables: $broken_links, broken_ln.  #
                      #----------------------------------------------------------------------#
                      {
                        if [ $opt_b -ne 1 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Skipping broken symbolic links check (_BSL_)." | $teelog
                           broken_links="Link check skipped."
                           broken_ln=0
                           echo "${sp}$dashes"    | $teelog
                           return
                        fi

                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking/removing broken symbolic links (_BSL_)." | $teelog

                        _BSL_max_time=`expr $max_proc_time \* 3` # This can take a while.

                        #--------------------------------------------------------#
                        # Run this in background.                                #
                        #--------------------------------------------------------#
                        _BSL_cmd="/usr/local/bin/linkcheck.pl -lr /"
                        echo "${sp}$_BSL_cmd"
                        $_BSL_cmd > $tmpwrk 2>&1 &

                        [ $opt_v -eq 1 ] \
                          && echo "${sp}TERMINATE $! $pidfil $_BSL_max_time"
                                        TERMINATE $! $pidfil $_BSL_max_time
                        wait # For BG job to complete normally or be TERMINATEd

                        broken_links=`grep -i 'Found [0-9].* broken links' $tmpwrk`
                        broken_links=`expr "$broken_links" : '.*: \(.*\)'` # Strip hostname
                        [ ."$broken_links" = . ] && broken_links="No report from '$_BSL_cmd'!"

                        broken_ln=`expr "$broken_links" : 'Found \([0-9][0-9]*\) *.*'`

                        sed "s/^/$sp/" $tmpwrk | $teelog
                        echo "${sp}$dashes"    | $teelog
                      } # "_BSL_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_CRITICAL_ID_MAIL()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking critical ID mail (_CCM_)." | $teelog

                        _CCM_fail_n=0
                        _CCM_vxvm_n=0
                        _CCM_mail_n=0
                        #--------------------------------------------------------------------#
                        # Check for process failures (by looking for mail to critical users).#
                        # Use the 'case' construct to add any others we might want checked.  #
                        #--------------------------------------------------------------------#
                        _CCM_purge_logins="" # List of users no longer having mail
                        for _CCM_login in $logins
                        do
                           [ ."`$AWK '/^'$_CCM_login':/' /etc/passwd`" = . ] && continue

                           echo "`date '+%Y-%m-%d %T'`" \
                             "Checking mail for $_CCM_login." | $teelog
                           _CCM_login_mail=$mail_dir/$_CCM_login
                           if [ -s "$_CCM_login_mail" ]; then
                              #----------------------------------------------------------#
                              # It's really tough to get a count on e-mails. We've tried #
                              # counting subject and sender lines.  Now we're trying     #
                              # Message-Id lines. We may have to divide that tally by 2. #
                              #----------------------------------------------------------#
                            # _CCM_mail_n=`grep "Subject: " $_CCM_login_mail | wc -l`
                            # _CCM_mail_n=`grep "Sender: "  $_CCM_login_mail | wc -l`
                              _CCM_mail_n=`grep -i "^Message-Id: " $_CCM_login_mail | wc -l`
                              mail_files_n=`expr $mail_files_n + $_CCM_mail_n`

                              echo "$_CCM_login" >> $notice_list

                              #------------------------------------------------#
                              # If this is root we're talking about here, then #
                              # check for veritas (sparc storage array) errors.#
                              #------------------------------------------------#
                              if [ $_CCM_login = "root" ]; then
                                 _CCM_fail_n=`grep "Subject: Volume Manager failures" \
                                    $_CCM_login_mail | wc -l`

                                 _CCM_vxvm_n=`grep "Subject: Attempted VxVM recovery" \
                                    $_CCM_login_mail | wc -l`

                                 _CCM_mail_n=`expr \`grep "Subject: " $_CCM_login_mail|wc -l\` \
                                   - $_CCM_fail_n - $_CCM_vxvm_n`

                                 if [ $_CCM_fail_n -gt 0 ]; then
                                    EMAIL_MSG "URGENT!! Volume Manager Failures" \
                                      "${sp}Check mail on $HOST for details"
                                 elif [ $_CCM_vxvm_n -gt 0 ]; then
                                    EMAIL_MSG "URGENT!! Attempted VxVM Recovery" \
                                      "${sp}Check mail on $HOST for details"
                                 fi
                                 [ $_CCM_mail_n -eq 0 ] && $continue # Iterate our for-loop
                              fi

                              #----------------------------------------------------------#
                              # For all users including root (unless it has iterated our #
                              # for-loop) do the following:  Just being here means that  #
                              # the user has mail.  The question remains, do they have   #
                              # one entry in $notice_list (the only other possibility is #
                              # more than one--can't get here with zero).                #
                              #----------------------------------------------------------#
                              if [ `grep "$_CCM_login" $notice_list | wc -l` -eq 1 ]; then
                                 _CCM_mail_n=`grep "Subject: " $_CCM_login_mail | wc -l`
                                 if [ $_CCM_mail_n -gt 0 ]; then
                                    grep -i '^Subject: ' $_CCM_login_mail \
                                     | sort -u | sed "s/^/$sp/" 1> $stderr 2>&1

                                    EMAIL_MSG "MAIL FOUND for $_CCM_login." \
                                      "${sp}'Subject:' lines follow:"       \
                                      "${sp}$dashes"                        \
                                      "FILE=$stderr"
                                 fi
                              else # No mail notification, but log it anyway
                                 grep -i '^Subject: ' $_CCM_login_mail \
                                  | sort | uniq | sed "s/^/$sp/" 1> $stderr 2>&1
                                 echo "`date '+%Y-%m-%d %T'`" \
                                   "MAIL FOUND for $_CCM_login."      | $teelog
                                 echo "${sp}'Subject:' lines follow:" | $teelog
                                 echo "${sp}$dashes"                  | $teelog
                                 cat $stderr                          | $teelog
                              fi
                           else # No mail? OK, add $_CCM_login to our purge list.
                              _CCM_purge_logins="$_CCM_purge_logins $_CCM_login"
                           fi # if [ -s "$_CCM_login_mail" ]; then
                        done # for _CCM_login in $logins

                        #----------------------------------------------------------#
                        # Purge any logins from $notice_list (if they're in there) #
                        # that had no mail (perhaps it's already been read).       #
                        #----------------------------------------------------------#
                        if [ `echo $_CCM_purge_logins | wc -w` -gt 0 ]; then
                           PURGE_MAIL_NOTICE_LIST $_CCM_purge_logins
                        fi

                        echo "${sp}$dashes" | $teelog
                      } # "_CCM_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_DEV_NULL_PERMS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'` Checking /dev/null permissions."| $teelog
                        _CNP_str_perms="crw-rw-rw-"
                        _CNP_dev_null='/dev/null'
                        _CNP_null_perms=`ls -al $_CNP_dev_null | $AWK '{print $1}'`
                        if [ $_CNP_null_perms = "lrwxrwxrwx" ]; then
                           #-----------------------------------------------#
                           # If /dev/null is actually a link, then check   #
                           # the permissions of the file to which it links.#
                           #-----------------------------------------------#
                           _CNP_null_perms=`ls -alL $_CNP_dev_null | $AWK '{print $1}'`
                           ls -al $_CNP_dev_null \
                            | $AWK -v sp="$sp" '{gsub(/[\t ]+/," ");print sp""$0}' | $teelog
                        fi

                        ls -alL $_CNP_dev_null \
                         | $AWK -v sp="$sp" '{gsub(/[\t ]+/," ");print sp""$0}' | $teelog

                        if [ "$_CNP_null_perms" = "$_CNP_str_perms" ]; then
                           $ECHO "${sp}$_CNP_dev_null Permissions OK ($_CNP_str_perms)." \
                            | $teelog
                        else
                           EMAIL_MSG "WARNING: /dev/null Permissions Problem"         \
                             "${sp}$_CNP_dev_null permissions NOT '$_CNP_str_perms'!" \
                             "${sp}Permissions are: '$_CNP_null_perms'"
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_CNP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_PARFILE_FOR_UPDATES() # Note: Since this function is expected    #
                      #---------------------------# to be the very first function called,    #
                      # it assigns all its output to $prelims where it will be printed later #
                      # (assuming all goes well--$prelims will print sooner if anything goes #
                      # amuck).  Only this function behaves in this manner.                  #
                      #----------------------------------------------------------------------#
                      {
                        ctlfile=$script_home/$name_root.ctl
                        #--------------------------------------------------------------#
                        # If janitor.master_par is in use (possibly being FTP'd here)  #
                        # or a control file is found (meaning janitor parameter file   #
                        # update is in progress), notify all that we're skipping this  #
                        # janitor run.                                                 #
                        #--------------------------------------------------------------#
                        if [ ."`fuser $parfile_master 2> /dev/null`" != . -o -f $ctlfile ]
                        then
                           $ECHO "$prelims" 1>&2
                           EMAIL_MSG "NOTICE $script_name"                      \
                                "${sp}Parameter file ($parfile) being updated." \
                                "${sp}Skipping $0 $args.  $script_name terminated."
                           EXIT 1
                        fi

                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Checking parameter file updates."

                        #--------------------------------------------------------------#
                        # Compare timestamps in $parfile and $parfile_master.  If they #
                        # differ, then create a new in $parfile from the master and    #
                        # continue.  If they are identical, then run as usual.         #
                        #--------------------------------------------------------------#
                        _CPF_awk_out=`$AWK -v sp="$sp" -v verbose=$opt_v \
                          'BEGIN {
                                    if (ARGC != 3) exit 4
                                    p = 1
                                    f[1] = ARGV[1]; time[1] = ""; n[1] = 0
                                    f[2] = ARGV[2]; time[2] = ""; n[2] = 0
                                    target = "^[\t ]*\043[\t ]*JANITOR_PARFILE_TIME[\t ]*=[\t ]*"
                                    yyyy_mm_dd = "20[0-9][0-9]\-[01][0-9]\-[0-3][0-9]"
                                    hh_mi_ss   = "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]"
                                    pattern    = target""yyyy_mm_dd" "hh_mi_ss
                                    if (verbose) print sp"pattern=|"pattern"|"
                                 }
                           #-----------------------------------------------------------#
                           # For lines matching our timestamp pattern, ..              #
                           #-----------------------------------------------------------#
                           $0 ~ pattern \
                           {
                             sub(/[\t ]+=[\t ]+/,"=") # Remove whitespace around =-sign
                             if (verbose) print sp"\$0=|"$0"|"

                             p = (FILENAME == ARGV[1]) ? 1 : 2 # Processing file 1 or 2?

                             n[p]++
                             match($0, yyyy_mm_dd" "hh_mi_ss)
                             time[p] = substr($0,RSTART,RLENGTH) # Save timestamp
                             if (verbose) print sp"==> time["p"]=|"time[p]"|"
                           }

                           END {
                                 if (ARGC != 3)
                                 {
                                   print sp"Insufficient args for parameter file check."
                                   exit 6
                                 }

                                 if (n[1] > 1 || n[2] > 1)
                                 {
                                   if (n[1] > 1)
                                   {
                                     print sp"Too many timestamps in "ARGV[1]"!"
                                     exit 5
                                   }
                                   if (n[2] > 1)
                                   {
                                     print sp"Too many timestamps in "ARGV[2]"!"
                                     exit 4
                                   }
                                 }

                                 if (n[1] == 0 || n[2] == 0)
                                 {
                                   if (n[1] == 0)
                                   {                   # Not found in janitor.master_par
                                     print sp"Timestamp not found in "ARGV[1]"!"
                                     exit 3
                                   }

                                   if (n[2] == 0)
                                   {                   # Not found in janitor.par
                                     print sp"Timestamp not found in "ARGV[2]"!"
                                     exit 2
                                   }
                                 }

                                 if (time[1] != time[2])
                                 {
                                   print sp"Updated parameter file detected.",
                                     "\n"sp""ARGV[1]"=|"time[1]"|",
                                     "\n"sp""ARGV[2]"=|"time[2]"|"
                                   exit 1
                                 }

                                 print sp"Parameter file up to date."
                                 exit 0 # Timestamps identical.
                               }' $parfile_master $parfile`
                        _CPF_status=$?
                        prelims="$prelims\n$_CPF_awk_out"

                        #----------------------------------------------------------------#
                        # If awk status indicates a change, then create new $parfile.    #
                        #----------------------------------------------------------------#
                        if [ $_CPF_status -eq 1 -o $_CPF_status -eq 2 ]; then
                           #-------------------------------------------------------------#
                           # Check this one more time (to minimize multiple simultaneous #
                           # creations of this file).                                    #
                           #-------------------------------------------------------------#
                           if [ ."`fuser $parfile_master 2> /dev/null`" != . -o -f $ctlfile ]
                           then
                              $ECHO "$prelims" 1>&2
                              EMAIL_MSG "NOTICE $script_name"                      \
                                   "${sp}Parameter file ($parfile) being updated." \
                                   "${sp}Skipping $0 $args.  $script_name terminated."
                              EXIT 1
                           fi
                           echo $$ > $ctlfile
                           prelims="$prelims\n`date '+%Y-%m-%d %T'` Creating new $parfile."

                           #-----------------------------------------------------------#
                           # If one exists, save the current parameter file.           #
                           #-----------------------------------------------------------#
                           if [ -s "$parfile" ]; then
                              prelims="$prelims\n`CP_EXIT_ERR $parfile ${parfile}'_bak'`"
                              [ $? -ne 0 ] && EXIT 1
                           fi

                           #-----------------------------------------------------------#
                           # Create new $parfile, extracting config info from master.  #
                           # Note the #=> MUST be separated from configuration text by #
                           # whitespace.                                               #
                           #-----------------------------------------------------------#
                           $AWK -v sp="$sp"            \
                                -v verbose=$opt_v      \
                                -v hostname=`uname -n` \
                             'BEGIN {
                                      p = q   = 1
                                      export  = ""
                                      all     = "[\t ]+#=> [Aa][Ll][Ll][\t ]*.*"
                                      host    = "[\t ]+#=> [A-Za-z0-9.\t ]*[\!]*"hostname"[\t ]*.*"
                                      exclude = "[\t ]+#=> .*\!"hostname
                                      pattern = all"|"host
                                      if (verbose) # Print to stderr
                                      {
                                        print "2> all    =|"all    "|" | "cat 1>&2"
                                        print "2> host   =|"host   "|" | "cat 1>&2"
                                        print "2> exclude=|"exclude"|" | "cat 1>&2"
                                        print "2> pattern=|"pattern"|" | "cat 1>&2"
                                      }
                                    }
                            # / T E S T / { print "=> " $0 | "cat 1>&2" } ## T E S T ##
                              $0 ~ pattern \
                              {
                                if (match($0,all) && match($0,exclude)) next
                              # print "==>" $0 | "cat 1>&2" ## T E S T ##

                                sub(pattern,"") # Remove the pattern from line.
                                line[p++] = $0  # Save the line as is, even if blank.
                              }
                              END {
                                    for (q=1; q<=p; q++) {print line[q]}
                                  }' $parfile_master > $parfile
                           CPF_status=$?

                           [ $opt_v -eq 1 ] && cat $parfile

                           #-----------------------------------------------------------#
                           # Check the creation status.  Restore saved config file     #
                           # if there was a problem.                                   #
                           #-----------------------------------------------------------#
                           if [ $CPF_status -eq 0 ]; then
                              prelims="$prelims\n`date '+%Y-%m-%d %T'` New $parfile creation successful."
                           else
                              $ECHO "$prelims" 1>&2
                              EMAIL_MSG "ALERT $script_name"                                \
                                "${sp}$parfile creation completed with $CPF_status status." \
                                "${sp}Restoring last good $parfile."
                              MV_EXIT_ERR ${parfile}"_bak" $parfile
                           fi

                           RM_EXIT_ERR $ctlfile
                        elif [ $_CPF_status -ne 0 ]; then
                           EMAIL_MSG "ERROR $script_name:$_CPF_name()" \
                             "${sp}Parameter file timestamp problems." \
                             "${sp}$_CPF_awk_out"                      \
                             "${sp}$script_name terminated."
                           EXIT 1
                        fi # if [ $_CPF_status -eq 1 -o $_CPF_status -eq 2 ]; then
                      } # "_CPF_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_N_ROLL_CRON_LOG() # Report /var/cron/log size, optionally        #
                      #                 pruning log if it exceeds $cronlog_size by rolling   #
                      #                 it over (akin to what happens to /var/adm/messages). #
                      #----------------------------------------------------------------------#
                      {
                        _CRC_name='CHECK_N_ROLL_CRON_LOG'
                        _CRC_rollovers="None" # Default
                        echo "`date '+%Y-%m-%d %T'`" \
                           "Check $cronlog for excessive growth (_CRC_)." | $teelog
                        if [ ! -f "$cronlog" ]; then # $cronlog a global var
                           EMAIL_MSG "ERROR $script_name:$_CRC_name()"              \
                             "${sp}$cronlog missing!  Killing and restarting cron." \
                             "${sp}$script_name continues."
                           CRON_STOP && sleep 5 && CRON_START # ()
                           _CRC_status=$?
                        elif [ ! -s "$cronlog" ]; then
                           EMAIL_MSG "ERROR $script_name:$_CRC_name()"                     \
                             "${sp}$cronlog is zero length!  Killing and restarting cron." \
                             "${sp}$script_name continues."
                           CRON_STOP && sleep 5 && CRON_START # ()
                           _CRC_status=$?
                        else
                           _CRC_bytes=`expr \`wc -c < $cronlog\` + 0`
                           _CRC_fmt_bytes=`FORMAT_NUM_WITH_COMMAS $_CRC_bytes`
                           if [ $_CRC_bytes -gt $cronlog_size ]; then
                              echo "`date '+%Y-%m-%d %T'`" \
                                "$cronlog has grown to $_CRC_fmt_bytes bytes." | $teelog
                              _CRC_rollovers="$_CRC_rollovers $cronlog"
                              if [ $opt_r -eq 1 ]; then
                                 echo "${sp}Rolling over $cronlog."            | $teelog
                                 CRON_STOP # ()
                                 _CRC_status=$?
                                 if [ $_CRC_status -eq 0 ]; then
                                    for _CRC_q in `RANGE_NUMS $cronlog_num-1`
                                    do
                                       [ ."$_CRC_q" = . ] && break
                                       _CRC_p=`expr $_CRC_q - 1`
                                       if [ -f "$cronlog.$_CRC_p" ]; then
                                          MV_EXIT_ERR $cronlog.$_CRC_p $cronlog.$_CRC_q
                                       elif [ -f "$cronlog.${_CRC_p}.Z" ]; then
                                          MV_EXIT_ERR $cronlog.$_CRC_p".Z" \
                                                      $cronlog.$_CRC_q".Z"
                                       fi
                                    done
                                    MV_EXIT_ERR $cronlog $cronlog".0"
                                    CRON_START # ()
                                    _CRC_status=$?
                                 fi
                                 _CRC_rollovers="$_CRC_rollovers (status=$_CRC_status)"
                              fi
                           else
                              cronlog_size=`FORMAT_NUM_WITH_COMMAS $cronlog_size`
                              echo "`date '+%Y-%m-%d %T'`"         \
                                 "$cronlog size ($_CRC_fmt_bytes)" \
                                 "within acceptable $cronlog_size byte limit." | $teelog
                           fi
                        fi

                        #----------------------------------------------------#
                        # Compress any uncompressed rolled-over files.  If a #
                        # compressed file exists already, remove it first.   #
                        #----------------------------------------------------#
                        for _CRC_file in `ls $cronlog.? 2> /dev/null  \
                                           | $AWK '/\.[0-9]+$/ {print}'`
                        do
                           [ -f "${_CRC_file}$suffix" ] && RM_EXIT_ERR ${_CRC_file}$suffix
                           echo "`date '+%Y-%m-%d %T'`" \
                             "$compress -v $_CRC_file"                      | $teelog
                              $compress -v $_CRC_file 2>&1 | sed "s/^/$sp/" | $teelog
                        done

                        ls -al $cronlog* | sed "s/^/$sp/" | $teelog
                        echo "${sp}$dashes"               | $teelog
                        return $_CRC_status
                      } # "_CRC_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_N_ROLL_WTMP_FILESIZES() # Report /var/adm/wtmp* file sizes,      #
                      #       optionally pruning the log if it exceeds $wtmp_size by rolling #
                      #       it over (like what happens to /var/adm/messages does).         #
                      #----------------------------------------------------------------------#
                      {
                        _CRW_rollovers="None"
                        #------------------------------------------------------#
                        # The following 'ls' lists only /var/adm/wtmp*.[0-9]+  #
                        # files, and excludes compressed (.Z) files.           #
                        #------------------------------------------------------#
                        for _CRW_file in `ls $wtmp_dir/wtmp* 2> /dev/null \
                                            | $AWK '! /\.[0-9]+/ {print}'`
                        do
                           echo "`date '+%Y-%m-%d %T'`" \
                              "Check $_CRW_file for excessive growth (_CRW_)." | $teelog
                           _CRW_bytes=`expr \`wc -c < $_CRW_file\` + 0`
                           _CRW_fmt_bytes=`FORMAT_NUM_WITH_COMMAS $_CRW_bytes`
                           if [ $_CRW_bytes -gt $wtmp_size ]; then
                              echo "`date '+%Y-%m-%d %T'`" \
                                "$_CRW_file has grown to $_CRW_fmt_bytes bytes." | $teelog
                              if [ $opt_r -eq 1 ]; then
                                 _CRW_rollovers="$_CRW_rollovers $_CRW_file"
                                 echo "${sp}Rolling over $_CRW_file." | $teelog
                                 _CRW_perms=`GET_FILE_PERMS $_CRW_file`

                                 for _CRW_q in `RANGE_NUMS $wtmp_num-1`
                                 do
                                    [ ."$_CRW_q" = . ] && break
                                    _CRW_p=`expr $_CRW_q - 1`
                                    if [ -f "$_CRW_file.$_CRW_p" ]; then
                                       MV_EXIT_ERR $_CRW_file"."$_CRW_p \
                                                   $_CRW_file"."$_CRW_q
                                    elif [ -f "$_CRW_file.${_CRW_p}.Z" ]; then
                                       MV_EXIT_ERR $_CRW_file"."$_CRW_p".Z" \
                                                   $_CRW_file"."$_CRW_q".Z"
                                    elif [ -f "$_CRW_file.${_CRW_p}.gz" ]; then
                                       MV_EXIT_ERR $_CRW_file"."$_CRW_p".gz" \
                                                   $_CRW_file"."$_CRW_q".gz"
                                    fi
                                 done

                                 #-----------------------------------------------------#
                                 # After rolling over the log, touch it and restore    #
                                 # the file's original permissions.                    #
                                 #-----------------------------------------------------#
                               # CP_EXIT_ERR          $_CRW_file $_CRW_file".0"
                               # CP_DEV_NULL_EXIT_ERR $_CRW_file
                                 MV_EXIT_ERR    $_CRW_file $_CRW_file".0"
                                 TOUCH_EXIT_ERR $_CRW_file
                                 CHMOD_EXIT_ERR $_CRW_perms "$_CRW_file"
                              fi
                           else
                              echo "`date '+%Y-%m-%d %T'`"           \
                                 "$_CRW_file size ($_CRW_fmt_bytes)" \
                                 "within acceptable limit ($wtmp_size)." | $teelog
                           fi
                        done

                        #----------------------------------------------------#
                        # Compress any uncompressed rolled-over files.  If a #
                        # compressed file exists already, remove it first.   #
                        #----------------------------------------------------#
                        for _CRW_file in `ls $wtmp_dir/wtmp* 2> /dev/null \
                                            | $AWK '/\.[0-9]+$/ {print}'`
                        do
                           [ -f "${_CRW_file}$suffix" ] && RM_EXIT_ERR ${_CRW_file}$suffix
                           echo "`date '+%Y-%m-%d %T'`" \
                             "$compress -v $_CRW_file"                      | $teelog
                              $compress -v $_CRW_file 2>&1 | sed "s/^/$sp/" | $teelog
                        done

                        ls -al $wtmp_dir/wtmp* | sed "s/^/$sp/" | $teelog
                        echo "${sp}$dashes" | $teelog
                      } # "_CRW_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_PASSWD_FOR_UID_0()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking /etc/passwd for UID 0." | $teelog

                        _CPU_ids=`$AWK -v sp="$sp" \
                          'BEGIN {
                                   FS=":"
                                   p=0
                                 }
                                 {
                                   if ($3 == 0 && $1 != "root")
                                   {
                                     p++
                                     line[p] = $0
                                   }
                                 }
                           END   {
                                   if (p == 0)
                                   {
                                     print sp"None found."
                                     exit p
                                   }

                                   print sp"UID 0 found for the following non-root ",
                                     "users (_CPU_):"
                                   for (q=0; q<=p; q++) {print sp"      "line[q]}
                                   exit p
                                 }' /etc/passwd`
                        zero_uid_n=$?
                        zero_uids=`echo $_CPU_ids | $AWK 'BEGIN {FS=":"} {print $2}'`

                        echo "$_CPU_ids"    | $teelog
                        echo "${sp}$dashes" | $teelog
                      } # "_CPU_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_ROOT_DIR_PERMS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking / (root) directory permissions." | $teelog
                        _CRP_oct_perms="0755"        # Octal value permissions
                        _CRP_str_perms="drwxr-xr-x"  # String (ls) permissions
                        _CRP_root_perms=`expr "\`ls -ald /\`" : '\(d.........\) .*'`
                        if [ "$_CRP_root_perms" = "$_CRP_str_perms" ]; then
                           echo "${sp}/ (root) permissions OK ($_CRP_str_perms)." \
                            | $teelog
                        else
                           CHMOD_EXIT_ERR $_CRP_oct_perms /
                           _CRP_new_perms=`expr "\`ls -ald /\`" : '\(d.........\) .*'`
                           EMAIL_MSG "NOTICE: / (root) Permissions Problem"          \
                             "${sp}/ (root) permissions NOT $_CRP_oct_perms!!"       \
                             "${sp}Permissions are currently:  '$_CRP_root_perms'"   \
                             "${sp}Changed'em to $_CRP_oct_perms ($_CRP_str_perms)." \
                             "${sp}Permissions after chmod are: '$_CRP_new_perms'"
                        fi
                      } # "_CRP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_TMP_DIR_PERMS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking /tmp and /var/tmp directory permissions." | $teelog
                        _CTP_oct_perms="1777"        # Octal value permissions.
                        _CTP_1777_perms="drwxrwxrwt" # String perms (ls) with sticky bit.
                        _CTP_0777_perms="drwxrwxrwx" # String permissions without sticky bit.
                        _CTP_fil_perms=""            # Just so you know what variabls we use.
                        _CTP_new_perms=""            # Assignment asts as a flag as well.
                        #----------------------------------------------------------------#
                        # I use the sticky bit on these temp directories because they    #
                        # are world-writable (meaning others can trash your temp files). #
                        # Using the sticky bit limits file renaming/removal ability to   #
                        # the file's owner, the directory owner, and superuser (root).   #
                        #----------------------------------------------------------------#
                        for _CTP_dir in /tmp /var/tmp
                        do
                           _CTP_fil_perms=`expr "\`ls -ald $_CTP_dir\`" : '\(d.........\) .*'`
                           if [ "$_CTP_fil_perms" = "$_CTP_1777_perms" ]; then
                              echo "${sp}$_CTP_dir permissions OK ($_CTP_fil_perms)." \
                               | $teelog
                              continue # Iterate the loop
                           elif [ "$_CTP_fil_perms" = "$_CTP_0777_perms" ]; then
                              CHMOD_EXIT_ERR $_CTP_oct_perms "$_CTP_dir"
                              _CTP_new_perms=`expr "\`ls -ald $_CTP_dir\`" : '\(d.........\) .*'`
                           else
                              CHMOD_EXIT_ERR $_CTP_oct_perms "$_CTP_dir"
                              _CTP_new_perms=`expr "\`ls -ald $_CTP_dir\`" : '\(d.........\) .*'`
                           fi

                           #-------------------------------------------------------#
                           # If $_CTP_new_perms is assigned anything, then some    #
                           # discrepency was found. so notify responsible persons. #
                           #-------------------------------------------------------#
                           if [ .$_CTP_new_perms != . ]; then
                              EMAIL_MSG "NOTICE: $_CTP_dir Permissions Incorrect"        \
                                "${sp}$_CTP_dir permissions NOT $_CTP_oct_perms!!"       \
                                "${sp}Permissions are currently: '$_CTP_fil_perms'"      \
                                "${sp}Changed'em to $_CTP_oct_perms ($_CTP_1777_perms)." \
                                "${sp}Permissions after chmod are: '$_CTP_new_perms'"
                              _CTP_new_perms=""
                           fi
                        done
                      } # "_CTP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHECK_VAR_MSGS_PERMS()
                      #----------------------------------------------------------------------#
                      {
                        _CVM_dir=`dirname $messages`
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Checking $messages* file permissions." | $teelog
                        _CVM_oct_perms="0644"        # Octal value permissions
                        _CVM_str_perms="-rw-r--r--"  # String (ls) permissions
                        _CVM_cwd=`pwd`
                        _CVM_status=0

                        _CVM_find_cmd="find $_CVM_dir -xdev -type f"
                        _CVM_find_cmd="$_CVM_find_cmd -name 'messages*'"
                        _CVM_find_cmd="$_CVM_find_cmd ! -perm $_CVM_oct_perms -ls"

                        echo "`date '+%Y-%m-%d %T'` eval $_CVM_find_cmd" # No $teelog

                        eval $_CVM_find_cmd | $AWK '{sub(/\.\//,"",$NF);print $3, $NF}' \
                         | while read _CVM_fil_perms _CVM_file
                           do
                              CHMOD_EXIT_ERR $_CVM_oct_perms "$_CVM_file"
                              _CVM_new_perms=`ls -al $_CVM_file | $AWK '{print $1}'`
                              EMAIL_MSG "NOTICE: $_CVM_file Permissions Problem"        \
                                "${sp}$_CVM_file permissions NOT $_CVM_oct_perms!!"     \
                                "${sp}Permissions are currently: '$_CVM_fil_perms'"     \
                                "${sp}Changed'em to $_CVM_oct_perms ($_CVM_str_perms)." \
                                "${sp}Permissions after chmod are: '$_CVM_new_perms'"
                              _CVM_status=1
                           done

                        if [ $_CVM_status -eq 0 ]; then
                           echo "${sp}$messages* permissions A-OK" \
                             "($_CVM_str_perms)." | $teelog
                        fi

                        CHDIR_EXIT_ERR $_CVM_cwd
                        echo "${sp}$dashes" | $teelog
                      } # "_CVM_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CHMOD_SPECIFIC_FILES() # $1 = fileid of file containing files & perms. #
                      #                      # (primarily from janitor.fileperms).           #
                      #                      # $chmod_m = Global variable                    #
                      #----------------------------------------------------------------------#
                      {
                        _CSF_name='CHMOD_SPECIFIC_FILES'
                        if [ $# -lt 1 ]; then
                           echo "FATAL ERROR $script_name:$_CSF_name()" 1>&2
                           echo "${sp}Insufficient args."               1>&2
                           echo "${sp}Usage: $_CSF_name fileid"         1>&2
                           echo "${sp}$script_name terminated."         1>&2
                           EXIT 1
                        fi

                        if [ -f "$1" ]; then
                           _CSF_n=`$AWK '{sub(/#+*/,"");if (NF) print}' $1 | wc -l`
                           [ $_CSF_n -lt 1 ] && return # None listed in the file?  Return.

                           echo "`date '+%Y-%m-%d %T'`"                                  \
                             "Checking select file permissions from list in $1 (_CSF_)." \
                               | $teelog
                           echo 0 > $tmpwrk2 # Initial count (saved outside while-loop)
                           $AWK '{sub(/#.*/,"");if (NF) print}' $1 \
                            | while read _CSF_file _CSF_perms
                              do
                                 if [ -f "$_CSF_file" ]; then
                                    #------------------------------------------------------#
                                    # Don't chmod symbolic links.                          #
                                    # ---------------------------------------------------- #
                                    _CSF_1st_char=`expr "\`ls -al $_CSF_file\`" : '\(.\).*'`
                                    if [ ."$_CSF_1st_char" = .'l' ]; then
                                       echo "`date '+%Y-%m-%d %T'`" \
                                         "Skipping $_CSF_file -- it's a link." | $teelog
                                       continue # Iterate while loop
                                    fi
                                    #                                                      #
                                    #------------------------------------------------------#
                                    [ $verbose -eq 1 ] \
                                      && echo "${sp}Checking $_CSF_file" | $teelog

                                    _CSF_curr_perms=`GET_FILE_PERMS $_CSF_file`
                                    _CSF_adj_perms=`$AWK               \
                                      -v curr_perms="$_CSF_curr_perms" \
                                      -v desired_perms="$_CSF_perms"   \
                                      "$awk_perms_script"`

                                    #------------------------------------------------------#
                                    # If adjusted perms != desired perms (even if they're  #
                                    # less than the desired), report the difference anyway.#
                                    #------------------------------------------------------#
                                    if [ $_CSF_curr_perms -ne $_CSF_perms ]; then
                                       if [ $opt_c -eq 1 ]; then
                                          if [ $_CSF_adj_perms -ne $_CSF_perms ]; then
                                             echo "`date '+%Y-%m-%d %T'`"               \
                                               "Recommended permissions for $_CSF_file" \
                                               "are $_CSF_perms (current ="             \
                                               "$_CSF_curr_perms)." | $teelog
                                          fi
                                          ls -al $_CSF_file | sed "s/^/$sp/" | $teelog
                                       fi # if [ $opt_c -eq 1 ]; then
                                    fi

                                    if [ $_CSF_curr_perms -ne $_CSF_adj_perms ]; then
                                       if [ $opt_c -eq 1 ]; then
                                          #------------------------------------------#
                                          # The following changes file permissions:  #
                                          #------------------------------------------#
                                          eval echo "`date '+%Y-%m-%d %T'`"         \
                                            "Changing $_CSF_file permissions from," \
                                            "$_CSF_curr_perms to $_CSF_adj_perms." | $teelog
                                          ls -al $_CSF_file | sed "s/^/$sp/"       | $teelog
                                          $ECHO "`date '+%Y-%m-%d %T'`" \
                                            "eval chmod -f $_CSF_adj_perms $_CSF_file" | $teelog
                                             eval chmod -f $_CSF_adj_perms $_CSF_file

                                          _CSF_status=$?
                                          if [ $_CSF_status -ne $success ]; then
                                            $ECHO "`date '+%Y-%m-%d %T'`"               \
                                              "Failure changing $_CSF_file permissions" \
                                              "to $1." | $teelog
                                          else
                                             chmod_m=`expr $chmod_m + 1`
                                          fi
                                       else
                                          #------------------------------------------#
                                          # Following recommends changing file perms #
                                          #------------------------------------------#
                                          echo "`date '+%Y-%m-%d %T'`"                  \
                                            "Recommend changing $_CSF_file permissions" \
                                            "from, $_CSF_curr_perms to $_CSF_perms." | $teelog
                                       fi # if [ $opt_c -eq 1 ]; then
                                       ls -al $_CSF_file | sed "s/^/$sp/" | $teelog
                                    fi # if [ $_CSF_curr_perms -ne $_CSF_perms ]; then
                                 else
                                    #----------------------------------------------------#
                                    # This should help to keep list current.  When files #
                                    # are routinely missing, this reminds us to purge    #
                                    # them from our list.  HOWEVER, it is only to show   #
                                    # up when this process is run interactively.         #
                                    #----------------------------------------------------#
                                    if [ ."$TERM" != . ]; then
                                       $ECHO "${sp}List file !found: $_CSF_file."
                                    fi
                                 fi # if [ -f $_CSF_file ]; then
                              echo $chmod_m > $tmpwrk2 # Pass this count outside for-loop

                              done # while read _CSF_file _CSF_perms
                           chmod_m=`cat $tmpwrk2` # Pick up passed count
                           #-----------------------------------------------------------#
                           # If nothing was changed, then for the record, show'em what #
                           # we're using (from our list).                              #
                           #-----------------------------------------------------------#
                           if [ $chmod_m -eq 0 ]; then
                              $ECHO "`date '+%Y-%m-%d %T'`"                           \
                                    "All files match or exceed (are more restrictive" \
                                    "\n${sp}than) the following permission list:" | $teelog
                              $AWK -v sp="$sp" \
                                '{
                                    gsub(/#.*/    ,"")
                                    gsub(/^[\t ]*/,"")
                                    if ($0 !~ /^$/)
                                    {
                                       gsub(/^/,sp)
                                       print
                                    }
                                 }' $1 | $teelog
                           fi

                           echo "${sp}$dashes" | $teelog
                        fi # if [ -f $1 ]; then
                      } # "_CSF_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CRON_START()
                      #----------------------------------------------------------------------#
                      {
                        _CRS_process=`QUERY_PROCESS "$cron_demon"`   # ()
                        _CRS_status=$?

                        #---------------------------------------------------------#
                        # There should be none.  Period.  If there are, then fuss #
                        # about and return.                                       #
                        #---------------------------------------------------------#
                        if [ $_CRS_status -gt 0 ]; then
                           ps $ps_opts > $tmpwrk 2>&1
                           EMAIL_MSG "ERROR $script_name:$_CRS_name()"               \
                             "${sp}$cron_demon process running!  'ps' list follows." \
                             "${sp}Cron NOT started. $script_name continues."        \
                             "`sed \"s/^/$sp/\" $tmpwrk`"
                           return $_CRS_status
                        fi

                        echo "`date '+%Y-%m-%d %T'` $cron_start" | $teelog
                                                    $cron_start  > $tmpwrk 2>&1
                        sleep 10 # Give it some time to complete.

                        _CRS_process=`QUERY_PROCESS "$cron_demon"`   # ()
                        _CRS_status=$?

                        if [ $_CRS_status -eq 0 ]; then # Cron ! started
                           echo "${sp}'$cron_start' failed to start cron!" | $teelog
                           #-------------------------------------------#
                           # If running SunOs and cron fails to start, #
                           # then remove cron FIFO file and try again. #
                           #-------------------------------------------#
                           if [ ."$OZ" = ."sunos" ]; then
                              echo "${sp}Attempting restart." | $teelog

                              echo "`date '+%Y-%m-%d %T'`" \
                                "$rm -f /etc/cron.d/FIFO"     | $teelog
                                 $rm -f /etc/cron.d/FIFO 2>&1 | $teelog

                              echo "`date '+%Y-%m-%d %T'`" \
                                "$cron_start"     | $teelog
                                 $cron_start > $tmpwrk 2>&1
                           fi # if [ ."$OZ" = ."sunos" ]

                           sleep 10 # Give it more time to complete.

                           _CRS_process=`QUERY_PROCESS "$cron_demon"`   # ()
                           _CRS_status=$?
                           if [ $_CRS_status -eq 0 ]; then
                              ps $ps_opts > $tmpwrk 2>&1
                              EMAIL_MSG "ERROR $script_name:$_CRS_name()"    \
                                "${sp}'$cron_start' failed to start cron!"   \
                                "${sp}Check it out. $script_name continues." \
                                "`sed \"s/^/$sp/\" $tmpwrk`"
                           fi
                        else
                           [ -s "$tmpwrk" ]  && sed "s/^/$sp/" $tmpwrk             | $teelog
                           [ -f "$cronlog" ] && tail -20 $cronlog | sed "s/^/$sp/" | $teelog
                        fi # if [ $_CRS_status -eq 0 ]

                        #------------------------------------------------------------#
                        # Return success (0) if status > 0, else return failure (1). #
                        #------------------------------------------------------------#
                        [ $_CRS_status -gt 0 ] && return 0 || return 1
                      } # "_CRS_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      CRON_STOP()
                      #----------------------------------------------------------------------#
                      {
                        _CSTP_process=`QUERY_PROCESS "$cron_demon"`   # ()
                        _CSTP_status=$?

                        #------------------------------------------------------------#
                        # There should be only 1, max.  If more, then fuss about it  #
                        # and return.  If only one, try shutting it down properly.   #
                        #------------------------------------------------------------#
                        if [ $_CSTP_status -gt 1 ]; then
                           ps $ps_opts > $tmpwrk 2>&1
                           EMAIL_MSG "ERROR $script_name:$_CSTP_name()"           \
                             "${sp}Found multiple cron processes!  List follows." \
                             "${sp}$script_name continues."                       \
                             "`sed \"s/^/$sp/\" $tmpwrk`"
                        fi

                        echo "`date '+%Y-%m-%d %T'` $cron_stop" | $teelog
                                                    $cron_stop  > $tmpwrk 2>&1
                        sleep 10 # Give it some time to complete.

                        _CSTP_process=`QUERY_PROCESS "$cron_demon"`   # ()
                        _CSTP_status=$?
                        echo "${sp}2. \$_CSTP_status =|$_CSTP_status|"  | $teelog
                        echo "${sp}2. \$_CSTP_process=|$_CSTP_process|" | $teelog

                        if [ $_CSTP_status -gt 0 ]; then
                           ps $ps_opts > $tmpwrk 2>&1
                           EMAIL_MSG "ERROR $script_name:$_CSTP_name()"   \
                             "${sp}'$cron_stop' returned $_CSTP_status!"  \
                             "${sp}Check it out. $script_name continues." \
                             "`sed \"s/^/$sp/\" $tmpwrk`"
                        else
                           [ -s "$tmpwrk"  ] && sed "s/^/$sp/" $tmpwrk             | $teelog
                           [ -f "$cronlog" ] && tail -20 $cronlog | sed "s/^/$sp/" | $teelog
                        fi

                        #--------------------------------------------------#
                        # Return number of processes found (0 = success).  #
                        #--------------------------------------------------#
                        return $_CSTP_status
                      } # "_CSTP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      DISPLAY_TMPWRK()
                      #----------------------------------------------------------------------#
                      {
                        wait # for any errant BG jobs
                        [ -s "$tmpwrk" ] && cat $tmpwrk
                        echo "${sp}$dashes"
                        $rm -f $tmpwrk 2>&1 | $teelog
                      }

                      #----------------------------------------------------------------------#
                      DISPLAY_SETUID_SCRIPTS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Looking for set[ug]id executable scripts (perm 4000)." | $teelog

                        _DSS_n=0
                        _DSS_found=0

                        #--------------------------------------------------------------#
                        # NOTE: "/etc/lp/alerts/printer" is the only executable shell  #
                        # script having setuid/setgid file permissions allowed.        #
                        #--------------------------------------------------------------#
                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1
                        for _DSS_fs in $fs /tmp
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_DSS_fs." | $teelog
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_DSS_fs = '/' ]; then
                              _DSS_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _DSS_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _DSS_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #-----------------------------------------------------------------#
                           # Display the command before running it so anyone can cut-n-paste #
                           # it as needed. Note: the '\;' must remain outside the $_..._find #
                           # assignment or the find fails for incomplete statement.          #
                           #-----------------------------------------------------------------#
                           _DSS_find="find $_DSS_fs $exclude_fs $_DSS_opt -type f"
                           _DSS_find="$_DSS_find -perm -4000 -exec file {}"
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'` $_DSS_find \;" | $teelog
                           fi

                           #---------------------------------------#
                           # Run this in background.               #
                           #---------------------------------------#
                           eval $_DSS_find '\;' 2>&1                              \
                            | egrep -vi "permission denied|timed out|cannot open" \
                              >> $stderr &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           wait # For BG job to complete normally or be TERMINATEd

                           #---------------------------------------#
                           # If we snagged anything, then report.  #
                           #---------------------------------------#
                           if [ -s "$stderr" ]; then
                              $AWK -v sp="$sp" \
                                '{
                                   file=tolower($0)
                                   if (!                                         \
                                        (                                        \
                                           match(file,/executable shell script/) \
                                         ||                                      \
                                           match(file,/commands text/)           \
                                        )                                        \
                                      ) {next}
                                   if (match(file,/\/etc\/lp\/alerts\/printer/)) {next}

                                   gsub(/^[\t ]+/,"",$0)
                                   gsub(/[\t ]+$/,"",$0)
                                   sub(/:.*/,"",$0)
                                   "/usr/bin/ls -al " $0 | getline ls_out
                                   print sp""ls_out
                                 }' $stderr | sort -u +8 > $tmpwrk1 # Sort drops dup lines
                           fi

                           _DSS_found=`expr \`wc -l < $stderr\` + 0`
                           _DSS_n=`expr $_DSS_found - $_DSS_n`
                           echo "${sp}Files found in $_DSS_fs = $_DSS_n" | $teelog
                           _DSS_n=$_DSS_found
                        done # for _DSS_fs in $fs /tmp

                        #--------------------------------------------#
                        # Since these are hot, mail this list ASAP.  #
                        #--------------------------------------------#
                        echo "${sp}Total files found = $_DSS_found" | $teelog
                        _DSS_found=`expr \`wc -l < $tmpwrk1\` + 0`
                        if [ $_DSS_found -gt 0 -o -s "$tmpwrk1" ]; then
                           if [ $opt_m -eq 1 ]; then
                              EMAIL_MSG "$_DSS_found Set[UG]id files found (_DSS_)!" \
                                "${sp}List follows:"                                 \
                                "${sp}$dashes"                                       \
                                "FILE=$tmpwrk1"
                           else
                              echo "`date '+%Y-%m-%d %T'`" \
                                   "$_DSS_found Set[UG]id files found (_DSS_)!" | $teelog
                              echo "${sp}List follows:"                         | $teelog
                              echo "${sp}$dashes"                               | $teelog
                              cat $tmpwrk1                                      | $teelog
                           fi
                           suid_scripts_n=$_DSS_found
                        else
                           $ECHO "${sp}No set[ug]id scripts among the files.\n" | $teelog
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_DSS_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      ENSURE_GNUPG_PERMS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Ensuring GnuPG perms (_EGP_)." | $teelog
                        [ -d /.gnupg ] && CHOWN_EXIT_ERR root /.gnupg
                        FIND_AND_CHMOD -f 4755 gpg # ()
                        echo "${sp}$dashes" | $teelog
                      } # "_EGP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      EXAMINE_NETRC_FILES()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Examining all .netrc files (_ENF_)." | $teelog

                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1 $tmpwrk2

                        for _ENF_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_ENF_fs." | $teelog
                           cp /dev/null $stderr 2>&1
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_ENF_fs = '/' ]; then
                              _ENF_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _ENF_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _ENF_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #---------------------------------------------------------#
                           # Run find command in background.                         #
                           #---------------------------------------------------------#
                           _ENF_find="find $_ENF_fs $exclude_fs $_ENF_opt"
                           _ENF_find="$_ENF_find -name .netrc -print"
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'` $_ENF_find" | $teelog
                           fi
                           eval $_ENF_find 2>&1                                   \
                            | egrep -vi "permission denied|timed out|cannot open" \
                              > $tmpwrk1 &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           status=$?
                           wait # For BG job to complete normally or be TERMINATEd

                           [ -s "$stderr" ] && sed "s/^/$stderr_sp/" $stderr | $teelog

                           if [ -s "$tmpwrk1" ]; then
                              $AWK -v sp="$sp" -v opt_n=$opt_n \
                                '! /^\+? ?find / \
                                 { # Print filename, and if $opt_n, the contents as well.
                                   print sp""$0
                                   if (opt_n == 1)
                                     while ("/bin/cat "$0 | getline out != 0)
                                       if (out !~ /^[\t\n\r ]*$/) # Skip blank lines.
                                         print sp"   "out
                                   close("/bin/cat "$0)
                                 }' $tmpwrk1 | $teelog
                           fi
                           cat $tmpwrk1 >> $tmpwrk # This is that we, indeed, have files.
                        done # for _ENF_fs in $fs

                        if [ ! -s "$tmpwrk" ]; then
                           echo "`date '+%Y-%m-%d %T'` No .netrc files found!" | $teelog
                        fi

                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1 $tmpwrk2

                        echo "${sp}$dashes" | $teelog
                      } # "_ENF_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      EXAMINE_RHOSTS_FILES()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Examining all rhosts files (_ERF_)." | $teelog
                        unsafe_m=0 # Global variable

                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1 $tmpwrk2

                        for _ERF_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_ERF_fs." | $teelog
                           cp /dev/null $stderr 2>&1
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_ERF_fs = '/' ]; then
                              _ERF_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _ERF_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _ERF_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #-----------------------------------------------#
                           # Run find command in background.               #
                           #-----------------------------------------------#
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'`" \
                               "find $_ERF_fs $exclude_fs $_ERF_opt $rhost_pr" | $teelog
                           fi

                           #-----------------------------------------------#
                           # Run this in background and must have 'eval'.  #
                           #-----------------------------------------------#
                           eval find $_ERF_fs $exclude_fs $_ERF_opt $rhost_pr \
                              > $tmpwrk1 2> $tmpwrk2 &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           status=$?
                           wait # For BG job to complete normally or be TERMINATEd

                           [ -s "$stderr"  ] && sed "s/^/$stderr_sp/"  $stderr  | $teelog
                           [ -s "$tmpwrk2" ] && sed "s/^/$tmpwrk2_sp/" $tmpwrk2 \
                             | egrep -vi "permission denied|timed out|cannot open" | $teelog

                           if [ -s "$tmpwrk1" ]; then
                              for _ERF_fil in `cat $tmpwrk1`
                              do
                                 $AWK -v sp="$sp" \
                                   'BEGIN {
                                            n=0
                                            print sp""ARGV[1]
                                          }
                                    # Print "unsafe" lines here
                                    /^[\t ]*(\+[\t ]*$|\+[\t ]+\+[\t ]*$)/ \
                                    {
                                      n++
                                      print sp"     !! UNSAFE => "$0
                                      next
                                    }
                                    # All other lines print here
                                    {
                                      print sp"     "$0
                                    }
                                    END {exit n}' $_ERF_fil > $tmpwrk2 # Reusing $tmpwrk2
                                 unsafe_m=`expr $unsafe_m + $?`
                                 cat $tmpwrk2 | $teelog
                              done
                           fi

                           cat $tmpwrk1 >> $tmpwrk # This is how I know if there are any files
                        done # for _ERF_fs in $fs

                        if [ ! -s "$tmpwrk" ]; then
                           echo "`date '+%Y-%m-%d %T'` No .rhosts files found!" | $teelog
                        fi

                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1 $tmpwrk2

                        echo "${sp}$dashes" | $teelog
                      } # "_ERF_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      FIND_AND_CHMOD() # Args = [-f] mode fileid(s) (e.g. .rhosts .forward)  #
                      #                # $unsafe_n = Global variable                         #
                      #----------------------------------------------------------------------#
                      {
                        _FAC_name='FIND_AND_CHMOD'

                        if [ ."$1" = ."-f" ]; then
                           _FAC_opt_f=1
                           shift
                        else
                           _FAC_opt_f=0
                        fi

                        if [ $# -lt 2 ]; then
                           EMAIL_MSG "FATAL ERROR $script_name:$_FAC_name"  \
                             "${sp}Insufficient args."                      \
                             "${sp}Usage: $_FAC_name perms fileid ..."      \
                             "${sp}$script_name terminated."
                           EXIT 1
                        fi

                        #----------------------------------------------#
                        # Parse and verify perms are at least numeric. #
                        #----------------------------------------------#
                        ISINT $1
                        if [ $? -ne 1 ]; then
                           EMAIL_MSG "FATAL ERROR $script_name:$_FAC_name"  \
                             "${sp}'$1' not an integer!"                    \
                             "${sp}Usage: $_FAC_name perms fileid ..."      \
                             "${sp}$script_name continues."
                           return 1
                        fi
                        _FAC_perms=$1
                        shift

                      #--------------------------------------------------------------------#
                      _FAC_CHMOD() # Function within FIND_AND_CHMOD() to change perms.     #
                      #--------------------------------------------------------------------#
                      {
                         eval echo "`date '+%Y-%m-%d %T'`"               \
                           "Changing $_FAC_found_file permissions from," \
                           "$_FAC_curr_perms to $1." | $teelog
                         $ECHO "`date '+%Y-%m-%d %T'`" \
                           "eval chmod -f $1 $_FAC_found_file" | $teelog
                            eval chmod -f $1 $_FAC_found_file
                         _FAC_status=$?

                         ls -al $_FAC_found_file | sed "s/^/$sp/" | $teelog

                         if [ $_FAC_status -ne $success ]; then
                            $ECHO "`date '+%Y-%m-%d %T'`"                     \
                              "Failure changing $_FAC_found_file permissions" \
                              "to $1." | $teelog
                         else
                            unsafe_n=`expr $unsafe_n + 1`
                         fi
                      } # _FAC_CHMOD()

                        CP_DEV_NULL_EXIT_ERR $stderr

                        #--------------------------------------------------------------#
                        # Seek out files, changing weaker (less safe) perms as needed. #
                        #--------------------------------------------------------------#
                        echo 0 > $tmpwrk2 # Initial count (saved outside while-loop)
                        for _FAC_file in $*
                        do

                           CP_DEV_NULL_EXIT_ERR $tmpwrk1

                           _FAC_file=`echo $_FAC_file | sed 's/^.*\///'`
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Searching for $_FAC_file file(s) with unsafe permissions (_FAC_)." \
                               | $teelog

                           #-----------------------------------------------------------#
                           # First, find all target files bearing $_FAC_file name.     #
                           #-----------------------------------------------------------#
                           _FAC_list=""
                           for _FAC_fs in $fs
                           do
                              echo "`date '+%Y-%m-%d %T'` Checking $_FAC_fs." | $teelog
                              #----------------------------------------------------------#
                              # If we're searching root (/), then use -xdev to keep the  #
                              # search local (hopefully it won't descend into subdirs).  #
                              #----------------------------------------------------------#
                              if [ $_FAC_fs = '/' ]; then
                                 _FAC_opt="-xdev"
                              else                               # Not root dir and
                                 if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                    _FAC_opt="-local"            # so use -local.
                                 else                            # Else Linux, so don't use
                                    _FAC_opt=""                  # -local option (doesn't
                                 fi                              # know -local).
                              fi

                              #----------------------------------#
                              # Run find command in background.  #
                              #----------------------------------#
                              _FAC_find="find $_FAC_fs $exclude_fs $_FAC_opt -type f"
                              _FAC_find="$_FAC_find -type f -name \"$_FAC_file\" -print"
                              if [ $opt_v -eq 1 ]; then
                                 echo "`date '+%Y-%m-%d %T'` $_FAC_find" | $teelog
                              fi

                              #----------------------------------#
                              # Run this in background.          #
                              #----------------------------------#
                              eval $_FAC_find 2>&1                                   \
                               | egrep -vi "permission denied|timed out|cannot open" \
                                 > $tmpwrk1 &

                              [ $opt_v -eq 1 ] \
                                && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                              TERMINATE $! $pidfil $max_proc_time
                              status=$?
                              wait # For BG job to complete normally or be TERMINATEd
                           done # for _FAC_fs in $fs

                           [ -s "$stderr" ] && sed "s/^/$stderr_sp/" $stderr | $teelog

                           #---------------------------------------------------------#
                           # Run the list of files found, changing weaker files.     #
                           #---------------------------------------------------------#
                           for _FAC_found_file in `cat $tmpwrk1`
                           do
                              #----------------------------------------------------#
                              # Just in case it's part of an error msg that slips  #
                              # thru from the 'find' above, test file's existance. #
                              #----------------------------------------------------#
                              if [ ! -f "$_FAC_found_file" ]; then
                                 echo "`date '+%Y-%m-%d %T'`" \
                                   "Skipping '$_FAC_found_file' -- not found!" | $teelog
                                 continue # Iterate while loop
                              fi

                              #------------------------------------------------------#
                              # Don't chmod symbolic links (this is insurance -- the #
                              # above find command should exclude symbolic links).   #
                              _FAC_1st_char=`expr "\`ls -al $_FAC_found_file 2> /dev/null\`" : '\(.\).*'`
                              if [ ."$_FAC_1st_char" = .'l' ]; then
                                 echo "`date '+%Y-%m-%d %T'`" \
                                   "Skipping $_FAC_found_file -- it's a link." | $teelog
                                 continue # Iterate while loop
                              fi
                              #                                                      #
                              #------------------------------------------------------#
                              ls -al $_FAC_found_file | sed "s/^/$sp/" | $teelog

                              _FAC_curr_perms=`GET_FILE_PERMS $_FAC_found_file`

                              _FAC_adj_perms=`$AWK               \
                                -v curr_perms="$_FAC_curr_perms" \
                                -v desired_perms="$_FAC_perms"   \
                                "$awk_perms_script"`

                              #------------------------------------------------------#
                              # If adjusted perms != desired perms (even if they're  #
                              # less than the desired), report the difference anyway.#
                              #------------------------------------------------------#
                              if [ $_FAC_curr_perms -ne $_FAC_perms ]; then
                                 if [ $opt_c -eq 1 ]; then
                                    if [ $_FAC_adj_perms -ne $_FAC_perms ]; then
                                       if [ $_FAC_opt_f -eq 1 ]; then
                                          _FAC_CHMOD $_FAC_perms
                                       else
                                          echo "`date '+%Y-%m-%d %T'`"                     \
                                            "Recommended permissions for $_FAC_found_file" \
                                            "are $_FAC_perms (current=$_FAC_curr_perms)."  \
                                              | $teelog
                                       fi
                                    fi
                                 fi # if [ $opt_c -eq 1 ]; then
                              fi # if [ $_FAC_curr_perms -ne $_FAC_perms ]; then

                              if [ $_FAC_curr_perms -ne $_FAC_adj_perms ]; then
                                 if [ $opt_c -eq 1 -o $_FAC_opt_f -eq 1 ]; then
                                    _FAC_CHMOD $_FAC_adj_perms
                                 else
                                    #--------------------------------------------------#
                                    # Following recommends changing file permissions:  #
                                    #--------------------------------------------------#
                                    echo "`date '+%Y-%m-%d %T'`"                        \
                                      "Recommend changing $_FAC_found_file permissions" \
                                      "from, $_FAC_curr_perms to $_FAC_perms." | $teelog
                                 fi # if [ $opt_c -eq 1 -o $_FAC_opt_f -eq 1 ]; then
                              fi # if [ $_FAC_curr_perms -ne $_FAC_perms ]; then
                              echo $unsafe_n > $tmpwrk2 # Pass this count outside for-loop
                           done # for _FAC_found_file in `cat $tmpwrk1`
                        done # for _FAC_file in $*
                        unsafe_n=`cat $tmpwrk2`
                      } # "_FAC_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      FIND_ERRORS_IN_SYSLOGS() # Scan for errors newer than $msgs_back       #
                      #----------------------------------------------------------------------#
                      {
                        #------------------------------------------------------------------#
                        # 1st, create an array of days back dates in the form 'Mmm dd ...' #
                        #------------------------------------------------------------------#
                        _FES_mmm_dd_array=""
                        _FES_limit=20

                        #------------------------------------------------------------------#
                        # $syslogs contains /var/adm/messages and /var/log/syslog, however,#
                        # /var/log/syslog* is excluded because its files are too big.      #
                        #------------------------------------------------------------------#
                        for _FES_syslog in "${syslog_dir}messages"
                        do
                           #---------------------------------------------------------#
                           # Reduce the number of logs we scan by getting only those #
                           # with file dates more recent than our oldest date.       #
                           #---------------------------------------------------------#
                           _FES_fname=`basename $_FES_syslog`
                           _FES_yyyymmdd=`/usr/local/bin/dateplus -5`
                           _FES_mmdd=`echo $_FES_yyyymmdd | cut -c5-8`
                           _FES_logs=`ls -alr $_FES_syslog*                      \
                            | $AWK '/'$_FES_fname'\.*[0-9]*$/ {print $6,$7,$NF}' \
                            | $AWK -v mmdd=$_FES_mmdd                            \
                                'BEGIN {
                                         logs=""
                                         Mon["Jan"]="01" ; Mon["Jul"]="07"
                                         Mon["Feb"]="02" ; Mon["Aug"]="08"
                                         Mon["Mar"]="03" ; Mon["Sep"]="09"
                                         Mon["Apr"]="04" ; Mon["Oct"]="10"
                                         Mon["May"]="05" ; Mon["Nov"]="11"
                                         Mon["Jun"]="06" ; Mon["Dec"]="12"
                                       }
                                 /'$_FES_fname'\.*[0-9]*$/ \
                                 {
                                   ls_mmdd=Mon[$1]sprintf("%02d",$2)
                                   if (ls_mmdd >= mmdd)
                                     logs = logs" "$NF
                                 }
                                 END {print logs}'`

                           if [ ."$_FES_logs" = . ]; then
                              echo "`date '+%Y-%m-%d %T'`" \
                                "No messages files found in $syslog_dir!" | $teelog
                              continue
                           fi

                           echo "`date '+%Y-%m-%d %T'`"                                \
                             "Last $msgs_back days 'error's ($_FES_limit lines worth)" \
                             "from $_FES_logs" | $teelog

                           #-----------------------------------------------------------------#
                           # Now here's s really tricky part. First, I require that the file #
                           # list just handed to me be in oldest to newest order because we  #
                           # concatonate them to maintain their chronology.  Then we number  #
                           # their lines and sort those lines in reverse order by the line   #
                           # number.  We feed all that into $AWK which returns no more than  #
                           # the number of lines in $_FES_limit ($AWK does that last part    #
                           # for us).  Essentially, we're tailing the last nn lines of just  #
                           # the errors we find, listing them in LIFO order.                 #
                           #-----------------------------------------------------------------#
                           cat $_FES_logs | nl | sort -r +0 -1 \
                            | $AWK -v days_back=$msgs_back     \
                                   -v line_limit=$_FES_limit   \
                                   -v sp="$sp"                 \
                                   -v dateplus="$dateplus"     \
                                'BEGIN {
                                         #------------------------------------------------#
                                         # Create Mon[] hash with month numbers by name.  #
                                         #------------------------------------------------#
                                         Mon["Jan"]="01" ; Mon["Feb"]="02" ; Mon["Mar"]="03"
                                         Mon["Apr"]="04" ; Mon["May"]="05" ; Mon["Jun"]="06"
                                         Mon["Jul"]="07" ; Mon["Aug"]="08" ; Mon["Sep"]="09"
                                         Mon["Oct"]="10" ; Mon["Nov"]="11" ; Mon["Dec"]="12"

                                         #---------------------------------------------#
                                         # Add month names by number to the Mon[] hash #
                                         # (so we can look-em up either way).          #
                                         #---------------------------------------------#
                                         Mon["01"]="Jan" ; Mon["02"]="Feb" ; Mon["03"]="Mar"
                                         Mon["04"]="Apr" ; Mon["05"]="May" ; Mon["06"]="Jun"
                                         Mon["07"]="Jul" ; Mon["08"]="Aug" ; Mon["09"]="Sep"
                                         Mon["10"]="Oct" ; Mon["11"]="Nov" ; Mon["12"]="Dec"

                                         #---------------------------------------------#
                                         # Target error strings                        #
                                         #---------------------------------------------#
                                         t1="[Ee][Rr][Rr][Oo][Rr]"
                                         t2="[Pp][Aa][Nn][Ii][Cc]"
                                         t3="core dumped"
                                         t4="syncing file systems"

                                         #---------------------------------------------#
                                         # Assign today (Mon, mm, and dd) to arrays[1].#
                                         #---------------------------------------------#
                                         "/bin/date +%h%m%d" | getline MonMmDd
                                         Mon_dd[1] = substr(MonMmDd,1,3)
                                         mm        = substr(MonMmDd,4,2)
                                         dd        = substr(MonMmDd,6,2)
                                         mmdd[1]   = mm""dd
                                         Mon_dd[1] = Mon_dd[1]" "dd
                                         Mon_dd_hash[Mon[mm]" "sprintf("%02d",dd)] = 1

                                         #----------------------------------------------#
                                         # Now assign all the dates back to arrays[n].  #
                                         #----------------------------------------------#
                                         for (n=days_back;n>1;n--)
                                         {
                                           dateplus" -"(n-1) | getline yyyymmdd
                                           mm        = substr(yyyymmdd,5,2)
                                           dd        = substr(yyyymmdd,7,2)
                                           mmdd[n]   = mm""dd
                                           Mon_dd[n] = Mon[mm]" "sprintf("%02d",dd)
                                           Mon_dd_hash[Mon[mm]" "sprintf("%02d",dd)] = n
                                         }
                                         n=0

                                       } # End of BEGIN Section
                                       {
                                         if (n > line_limit)
                                           exit # User only wanted so many lines.
                                         sub(/^[\t ]*[0-9]+[\t ]*/,"")
                                       }
                                       /^[ADFJMNOS][aceopu][bcglnprtvy] [1-3 ][0-9] / \
                                       {
                                         line_Mon_dd = sprintf("%s %2d",$1, $2)
                                         line_mmdd   = Mon[$1]sprintf("%02d",$2)

                                        ##--------------------------------------------------##
                                        ## Redo this logic -- fails at EOY                  ##
                                        ## if (line_mmdd < mmdd[days_back])                 ##
                                        ##   exit # We are done when we find older record   ##
                                        ##--------------------------------------------------##
                                         if (line_Mon_dd in Mon_dd_hash)
                                         {
                                           if ($0 ~ /STDERR=/) {next} # Skip these

                                           if (match($0,t1)||match($0,t2)||match($0,t3)||match($0,t4))
                                           {
                                             print sp""$0
                                             n++
                                           }
                                         }
                                       }' | $teelog

                           echo "${sp}$dashes" | $teelog
                         # Now, go look at the next set of logs #
                        done # for _FES_syslog in $syslogs
                      } # "_FES_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LAST_20_LINES_SYSLOGS()
                      #----------------------------------------------------------------------#
                      {
                        for _L2L_syslog in $syslogs
                        do
                           if [ -s "$_L2L_syslog" ]; then
                              echo "`date '+%Y-%m-%d %T'`"       \
                                "LAST 20 LINES of $_L2L_syslog:" | $teelog
                              tail -20 $_L2L_syslog | sort -rM \
                                | sed "s/^ *//;/^$/d;s/^/$sp/" > $tmpwrk 2>&1
                              DISPLAY_TMPWRK | $teelog
                           fi
                        done
                        [ -f "$tmpwrk" ] && RM_EXIT_ERR $tmpwrk
                      } # "_L2L_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LIST_ALL_WW_FILES() # Showem all world writable files                  #
                                          # $ww_files_n = Global variable                    #
                      #----------------------------------------------------------------------#
                      {
                        if [ $opt_w -ne 1 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Skipping ALL WW-files list (_LWW_)." | $teelog
                           echo "${sp}$dashes"                     | $teelog
                           return
                        fi

                        $ECHO "`date '+%Y-%m-%d %T'`"                 \
                          "Look for world-writable files (perm 0002)" \
                          "\n${sp}found anywhere." | $teelog

                        _LWW_n=0
                        _LWW_found=0

                        CP_DEV_NULL_EXIT_ERR $stderr
                        for _LWW_fs in $fs /tmp
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_LWW_fs." | $teelog
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_LWW_fs = '/' ]; then
                              _LWW_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _LWW_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _LWW_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #-----------------------------------------------------------------#
                           # Display the command before running it so anyone can cut-n-paste #
                           # it as needed. Note: the '\;' must remain outside the $_LWW_find #
                           # assignment or the find fails for incomplete statement.          #
                           #-----------------------------------------------------------------#
                           _LWW_find="find $_LWW_fs $exclude_fs $_LWW_opt -type f"
                           _LWW_find="$_LWW_find -perm -0002 ! -perm -0003 -exec ls -al {}"
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'` $_LWW_find \;" | $teelog
                           fi

                           #-------------------------#
                           # Run this in background. #
                           #-------------------------#
                           eval $_LWW_find '\;' 2>&1                              \
                            | egrep -vi "permission denied|timed out|cannot open" \
                              >> $stderr &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           wait # For BG job to complete normally or be TERMINATEd

                           _LWW_found=`expr \`wc -l < $stderr\` + 0`
                           _LWW_n=`expr $_LWW_found - $_LWW_n`
                           echo "${sp}Files found in $_LWW_fs = $_LWW_n" | $teelog
                           _LWW_n=$_LWW_found
                        done # for _LWW_fs in ..
                        echo "${sp}Total files found = $_LWW_found (_LWW_)" | $teelog

                        #------------------------------------------#
                        # OK, show'em what we found (if anything). #
                        #------------------------------------------#
                        ww_files_n=$_LWW_found
                        if [ $_LWW_found -gt 0 -o -s "$stderr" ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "$_LWW_found WORLD WW files found (_LWW_)!" | $teelog
                           $AWK -v sp="$sp" \
                             '! /^$/ {sub(/^[\t ]+/,"");print sp"|"$0"|"}' $stderr | $teelog
                        else
                           echo "${sp}None found" | $teelog
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_LWW_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LIST_CORE_DUMP_FILES()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "List core dump files (_LCD_)." | $teelog

                        CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1

                        for _LCD_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_LCD_fs." | $teelog
                           cp /dev/null $stderr 2>&1
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_LCD_fs = '/' ]; then
                              _LCD_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _LCD_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _LCD_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #---------------------------------#
                           # Run find command in background. #
                           #---------------------------------#
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'`"           \
                               "find $_LCD_fs $exclude_fs $_LCD_opt" \
                               "-name core -type f -ls"  | $teelog
                           fi

                           #---------------------------------#
                           # Run this in background.         #
                           #---------------------------------#
                           eval find $_LCD_fs $exclude_fs $_LCD_opt -name core -type f -ls \
                              | egrep -vi "permission denied|timed out|cannot open"        \
                                >> $tmpwrk1 2>> $stderr &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           wait # For BG job to complete normally or be TERMINATEd

                        done # for _LCD_fs in $fs

                        _LCD_n=`wc -l < $tmpwrk1`

                        if [ $_LCD_n -gt 0 ]; then
                           $AWK -v sp="$sp" '$1 != "" {print sp""$0}' $tmpwrk1 > $tmpwrk
                           RM_EXIT_ERR $tmpwrk1

                           if [ -s "$tmpwrk" ]; then
                              sed "s/^/$stderr_sp/" $stderr >> $tmpwrk
                              DISPLAY_TMPWRK | $teelog
                           fi
                        else
                           echo "`date '+%Y-%m-%d %T'` No core dump files found." | $teelog
                           sed "s/^/$stderr_sp/" $stderr                          | $teelog
                           echo "${sp}$dashes"                                    | $teelog
                        fi

                        return $_LCD_n
                      } # "_LCD_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LIST_OLD_TMP_FILES()
                      #----------------------------------------------------------------------#
                      {
                        if [ $opt_t -ne 1 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Skipping old /tmp files list (_LTF_)." | $teelog
                           echo "${sp}$dashes"                       | $teelog
                           return
                        fi

                        echo "`date '+%Y-%m-%d %T'`" \
                          "List old /tmp files (_LTF_)." | $teelog
                        _LTF_users='-user 0 -o -user 1 -o -user 2 -user 3 -o -user 4'
                        #------------------------------------------------------------#
                        # Display the names of regular files in /tmp that have not   #
                        # been accessed in 3 days, then remove them from there.      #
                        # FYI: _LTF_users= 0/root, 1/daemon, 2/bin, 3/sys and 4/adm. #
                        #------------------------------------------------------------#
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Report /tmp files untouched in 7 days." | $teelog

                        _LTF_old_f=`find /tmp -type f -atime +7 \
                           ! \\( $_LTF_users \\) -print | wc -l`

                        if [ $_LTF_old_f -gt 0 ]; then
                           CP_DEV_NULL_EXIT_ERR $tmpwrk1 $tmpwrk $stderr

                           echo "`date '+%Y-%m-%d %T'`" \
                             "Recommend removing the following files:" | $teelog

                           find /tmp -type f -atime +7 ! \( $_LTF_users \) \
                             -exec ls -al {} \; >> $tmpwrk1 2>> $stderr
                           $AWK -v sp="$sp" '$1 != "" {print sp""$0}' $tmpwrk1 > $tmpwrk
                           sed "s/^/$stderr_sp/" $stderr >> $tmpwrk # Append stderr.

                           RM_EXIT_ERR $tmpwrk1 $tmpwrk $stderr

                        fi # if [ $_LTF_old_f -gt 0 ]
                        echo "${sp}$dashes" | $teelog

                        #------------------------------#
                        # Show-em what's left in /tmp  #
                        #------------------------------#
                        _LTF_remain_n=`find /tmp -ls \
                          | $AWK 'BEGIN {n=0} {n++} END {print n}'`

                        if [ $_LTF_remain_n -gt 0 ]; then
                           echo "`date '+%Y-%m-%d %T'` Here's a list of /tmp:" | $teelog
                           eval find /tmp -ls | $AWK -v sp="$sp" \
                             '!/^[\t ]*$/ {
                                             sub(/^ *[0-9]* *[0-9]* */,"")
                                             sub(/^ */,"")
                                             sub(/^/,sp)
                                             print
                                          }' | $teelog
                        fi

                        echo "${sp}$dashes" | $teelog
                      } # "_LTF_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LIST_SU_FILES()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Looking for any executable 'su' files (_LSU_)." | $teelog

                        _LSU_n=0
                        _LSU_found=0

                        CP_DEV_NULL_EXIT_ERR $stderr
                        for _LSU_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_LSU_fs." | $teelog
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_LSU_fs = '/' ]; then
                              _LSU_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _LSU_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _LSU_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #-----------------------------------------------------------------#
                           # Display the command before running it so anyone can cut-n-paste #
                           # it as needed. Note: the '\;' must remain outside the $_LSU_find #
                           # assignment or the find fails for incomplete statement.          #
                           #-----------------------------------------------------------------#
                           _LSU_find="find $_LSU_fs $exclude_fs $_LSU_opt -name su -type f"
                           _LSU_find="$_LSU_find -perm -0001 -exec ls -al {}"
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'` $_LSU_find \;" | $teelog
                           fi

                           #-------------------------#
                           # Run this in background. #
                           #-------------------------#
                           eval $_LSU_find '\;' 2>&1                              \
                            | egrep -vi "permission denied|timed out|cannot open" \
                              >> $stderr &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           wait # For BG job to complete normally or be TERMINATEd

                           _LSU_found=`expr \`wc -l < $stderr\` + 0`
                           _LSU_n=`expr $_LSU_found - $_LSU_n`
                           echo "${sp}Files found in $_LSU_fs = $_LSU_n" | $teelog
                           _LSU_n=$_LSU_found
                        done # for _LSU_fs in $fs

                        #------------------------------------------#
                        # OK, show'em what we found (if anything). #
                        #------------------------------------------#
                        su_files_n=$_LSU_found
                        if [ $_LSU_found -gt 0 -o -s "$stderr" ]; then
                           echo "`date '+%Y-%m-%d %T'`"           \
                             "$_LSU_found executable 'su' files found!" | $teelog
                           $AWK -v sp="$sp" \
                             '! /^$/ {sub(/^[\t ]+/,"");print sp"|"$0"|"}' $stderr | $teelog
                        else
                           echo "${sp}None found" | $teelog
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_LSU_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      LIST_WORLD_WX_FILES() # World writable and executable files!!          #
                                            # $wx_files_n = Global variable                  #
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Looking for world-wx files (perm 0003)." | $teelog

                        _LWX_n=0
                        _LWX_found=0

                        CP_DEV_NULL_EXIT_ERR $stderr
                        for _LWX_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_LWX_fs." | $teelog
                           #---------------------------------------------------------#
                           # If we're searching root (/), then use -xdev to keep the #
                           # search local (hopefully it won't descend into subdirs). #
                           #---------------------------------------------------------#
                           if [ $_LWX_fs = '/' ]; then
                              _LWX_opt="-xdev"
                           else                               # Not root dir and
                              if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                 _LWX_opt="-local"            # so use -local.
                              else                            # Else Linux, so don't use
                                 _LWX_opt=""                  # -local option (doesn't
                              fi                              # know -local).
                           fi

                           #-----------------------------------------------------------------#
                           # Display the command before running it so anyone can cut-n-paste #
                           # it as needed. Note: the '\;' must remain outside the $_LWX_find #
                           # assignment or the find fails for incomplete statement.          #
                           #-----------------------------------------------------------------#
                           _LWX_find="find $_LWX_fs $exclude_fs $_LWX_opt -type f"
                           _LWX_find="$_LWX_find -perm -0003 -exec ls -al {}"
                           if [ $opt_v -eq 1 ]; then
                              echo "`date '+%Y-%m-%d %T'` $_LWX_find \;" | $teelog
                           fi

                           #-------------------------#
                           # Run this in background. #
                           #-------------------------#
                           eval $_LWX_find '\;' 2>&1                              \
                            | egrep -vi "permission denied|timed out|cannot open" \
                              >> $stderr &

                           [ $opt_v -eq 1 ] \
                             && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                           TERMINATE $! $pidfil $max_proc_time
                           wait # For BG job to complete normally or be TERMINATEd

                           _LWX_found=`expr \`wc -l < $stderr\` + 0`
                           _LWX_n=`expr $_LWX_found - $_LWX_n`
                           echo "${sp}Files found in $_LWX_fs = $_LWX_n" | $teelog
                           _LWX_n=$_LWX_found
                        done # for _LWX_fs in $fs

                        #------------------------------------------#
                        # OK, show'em what we found (if anything). #
                        #------------------------------------------#
                        wx_files_n=$_LWX_found
                        if [ $_LWX_found -gt 0 -o -s "$stderr" ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "$_LWX_found WORLD WX files found (_LWX_)!" | $teelog
                           $AWK -v sp="$sp" \
                             '! /^$/ {sub(/^[\t ]+/,"");print sp"|"$0"|"}' $stderr | $teelog
                        else
                           echo "${sp}None found" | $teelog
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_LWX_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      PURGE_MAIL_NOTICE_LIST()
                      #----------------------------------------------------------------------#
                      {
                        _PMN_name="PURGE_MAIL_NOTICE_LIST"
                        if [ $# -lt 1 ]; then
                           EMAIL_MSG "FATAL ERROR $_PMN_name($script_name)"        \
                             "${sp}Insufficient arguments passed to $_PMN_name()." \
                             "${sp}Usage: $_PMN_name login [...]"                  \
                             "${sp}$script_name terminted."
                           EXIT $failure
                        fi


                        _PMN_purged=0
                        if [ -s "$notice_list" ]; then
                           for _PMN_login in $*
                           do
                              _PMN_n=`expr \`grep "$_PMN_login" $notice_list | wc -l\` + 0`
                              if [ $_PMN_n -gt 0 ]; then
                                 echo "`date '+%Y-%m-%d %T'`" \
                                   "Removing $_PMN_login from notice list." | $teelog
                                 sed "/$_PMN_login/d" $notice_list > $tmpwrk
                                 if [ $? -ne 0 ]; then
                                    EMAIL_MSG "ERROR $_PMN_name($script_name)"    \
                                      "${sp}Failure removing $_PMN_login from \c" \
                                        "\$notice_list,"                          \
                                      "${sp}$notice_list.  $script_name terminated."
                                    EXIT $failure
                                 fi

                                 MV_EXIT_ERR $tmpwrk $notice_list >> $log 2>&1
                                 _PMN_purged=1
                              fi
                           done
                        fi

                        #------------------------------------------------------------------#
                        # If, after removing preceding logins from $notice_list, we still  #
                        # have logins in the file, then prune them to just a single entry. #
                        #------------------------------------------------------------------#
                        if [ -s "$notice_list" ]; then
                           $AWK '{sub(/^[\t ]+/,"",$0);if ($0 ~ /^$/) next}' $notice_list \
                             | sort | uniq > $tmpwrk
                           if [ $? -ne 0 ]; then
                              EMAIL_MSG "ERROR $_PMN_name($script_name)"        \
                                "${sp}Failure removing duplicate logins from\c" \
                                "${sp}$notice_list.  $script_name terminated."
                              EXIT $failure
                           fi

                           [ $_PMN_purged -gt 0 ] && MV_EXIT_ERR $tmpwrk $notice_list >> $log 2>&1
                        fi

                      } # "_PMN_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      QUERY_PROCESS() # $1 = process argument string we seek                 #
                      #----------------------------------------------------------------------#
                      {
                        ps $ps_opts | $AWK -v ps_opts="$ps_opts" -v target="$@" \
                          'BEGIN \
                           {
                             if (target == "")
                             {
                               n = "-1"
                               exit
                             }
                             n=0 # Found counter.
                             pattern="^.*:.*("target"[\t ]*$)" # target[whitespace|linend]
                           }
                           #------------------------------------------------------------#
                           # Match our pattern (basically "target[whitespace|linend]"), #
                           # but exclude any "awk " and "vi " lines.                    #
                           #------------------------------------------------------------#
                           match($0,pattern) && ! /awk |vi / \
                           {
                             gsub( /[\t ]+/," ",$0) # Squeeze whitespace,
                             gsub(/^[\t ]+/,"", $0) #  strip leading whitespace
                             print $0               #   and print the dog.
                             n++
                           }
                           END \
                           {
                             if (n > 255) n=255

                             if (n == "-1")
                             {
                               print "Target string not supplied!"
                               n=255
                             }
                             else if (n == 0)
                               print "\""target"\"" " not_found in \047ps\047 query!"
                             exit n # Return number of cron demons found in exit status.
                           }'
                        return $?
                      } # "_QP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      REMOVE_OLD_CORE_DUMPS()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Remove core dump files unchanged in $old_core days." | $teelog

                        CP_DEV_NULL_EXIT_ERR $tmpwrk1 $tmpwrk $stderr

                        for _RCD_fs in $fs
                        do
                           echo "`date '+%Y-%m-%d %T'` Checking $_RCD_fs." | $teelog
                           find $_RCD_fs -xdev -name core -type f -mtime +$old_core \
                              -exec echo "rm -f " {} \; -exec ls -al {} \;          \
                              -exec $rm -f {} \; >> $tmpwrk1 2>> $stderr
                           $AWK -v sp="$sp" '$1 != "" {print sp""$0}' $tmpwrk1 > $tmpwrk
                        done
                        RM_EXIT_ERR $tmpwrk1

                        if [ -s "$tmpwrk" ]; then
                           sed "s/^/$stderr_sp/" $stderr >> $tmpwrk
                           DISPLAY_TMPWRK | $teelog
                        else
                           echo "`date '+%Y-%m-%d %T'` No old core dump files." | $teelog
                           sed "s/^/$stderr_sp/" $stderr                        | $teelog
                           echo "${sp}$dashes"                                  | $teelog
                        fi
                      } # "_RCD_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      REMOVE_WORLD_FILE_PERMS() # [-m nnn] = mtime +days                     #
                      #                         # $1       = World bits to turn off [wxr]    #
                      #                         # $2       = Target perms (e.g. 0002|0003)   #
                      #                         # $3-$n    = Target directories              #
                      #                         # $chmod_n = Global variable                 #
                      #----------------------------------------------------------------------#
                      {
                        if [ $1 = "-m" ]; then
                           _RWP_mtime="-mtime $2"
                           shift 2
                        else
                           _RWP_mtime=""
                        fi

                        _RWP_flag=""
                        _RWP_bits=$1
                        _RWP_perms=$2
                        shift 2

                        if [ $opt_c -eq 0 ]; then
                           _RWP_dirs=`echo "$*" \
                            | $AWK -v sp="$sp" '{
                                                  print ""
                                                  for (i=1;i<=NF;i++)
                                                  {
                                                     print sp""$i;
                                                  }
                                                }'`
                           $ECHO "`date '+%Y-%m-%d %T'`"                      \
                             "Skipping 'chmod o-$_RWP_bits' for files having" \
                             "'$_RWP_perms' perms in directories: $_RWP_dirs." | $teelog
                           echo "${sp}$dashes" | $teelog
                           return
                        fi

                        for _RWP_fs in $*
                        do
                           if [ -d $_RWP_fs ]; then
                              $ECHO "`date '+%Y-%m-%d %T'`"                           \
                                "Removing world-$_RWP_bits permission from world-xxx" \
                                "files (perm $_RWP_perms)\n${sp}found in $_RWP_fs." | $teelog

                              CP_DEV_NULL_EXIT_ERR $stderr $tmpwrk $tmpwrk1

                              #----------------------------------------------------------#
                              # If we're searching root (/), then use -xdev to keep the  #
                              # search local (hopefully it won't descend into subdirs).  #
                              #----------------------------------------------------------#
                              if [ $_RWP_fs = '/' ]; then
                                 _RWP_local="-xdev"
                              else                               # Not root dir and
                                 if [ ."$OZ" != ."linux" ]; then # not Linux? (SunOS),
                                    _RWP_local="-local"          # so use -local.
                                 else                            # Else Linux, so don't use
                                    _RWP_local=""                # -local option (doesn't
                                 fi                              # know -local).
                              fi

                              echo "${sp}find $_RWP_fs $exclude_fs $_RWP_local" \
                                          "-type f"                             \
                                          "-perm"                               \
                                          "-$_RWP_perms"                        \
                                           "$_RWP_mtime"                        \
                                          '-exec ls -al {} \;'                  \
                                          "| $AWK -v exclude='$ww_excl_dirs'"   \
                                                 "-v bits='$_RWP_bits'"         | $teelog

                              #------------------------------------------------#
                              # Run this in background.                        #
                              #------------------------------------------------#
                              find $_RWP_fs $exclude_fs $_RWP_local \
                                -type f                             \
                                -perm                               \
                                -$_RWP_perms                        \
                                 $_RWP_mtime                        \
                                -print 2>&1                         \
                                  | $AWK -v exclude="$ww_excl_dirs" \
                                         -v bits="$_RWP_bits"       \
                                      'BEGIN {
                                               ls    = "ls -al "
                                               chmod = "chmod o-"bits" "
                                               gsub(/ /,"|",exclude)
                                             }

                                       /cannot open|cannot read/           {next}
                                       /[Pp]ermission denied|[Tt]imed out/ {next}
                                       {
                                         if (match($0,exclude)) next

                                         #-----------------------------------------#
                                         # If the fileid has a double quote in it, #
                                         # then escape it.                         #
                                         #-----------------------------------------#
                                         if (match($0,/\042/))
                                           gsub(/\042/,"\\\042",$0)

                                                ls "\042"$0"\042" | getline ls_out
                                          close(ls "\042"$0"\042")
                                         cmd=chmod "\042"$0"\042"

                                         print "Before: "ls_out

                                         printf("%s\n", cmd)
                                         status = system(cmd); close(cmd)
                                         if (status == 0)
                                         {
                                                 ls "\042"$0"\042" | getline ls_out
                                           close(ls "\042"$0"\042")

                                           print "After:  "ls_out
                                         }
                                         else
                                         {
                                           print " (status="status")"
                                         }
                                       }' >> $tmpwrk1 2>> $stderr &

                              [ $opt_v -eq 1 ] \
                                && echo "${sp}TERMINATE $! $pidfil $max_proc_time"
                                              TERMINATE $! $pidfil $max_proc_time
                              wait # For BG job to complete normally or be TERMINATEd

                              $AWK -v sp="$sp" '$1 != "" {print sp$0}' $tmpwrk1 > $tmpwrk
                              sed "s/^/$stderr_sp/"                    $stderr >> $tmpwrk
                              _RWP_chmod_n=`$AWK 'BEGIN    {n=0    }
                                                  /After:/ {n++    }
                                                  END      {print n}' $tmpwrk`
                              chmod_n=`expr $chmod_n + $_RWP_chmod_n`
                              [ $_RWP_chmod_n -gt 0 ] && _RWP_flag=' (_RWP_)'
                              echo "${sp}Changed $_RWP_chmod_n files$_RWP_flag." >> $tmpwrk

                              DISPLAY_TMPWRK | $teelog
                           fi
                        done # for _RWP_fs in $*

                        [ -f "$tmpwrk1" ] && $rm -f $tmpwrk1
                      } # "_RWP_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      REPORT_RECENT_LOGIN_ACTIVITY()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'` Report recent login activity." | $teelog

                        _RRL_Mmm_dd=`date | cut -c5-10` # Any activity from today? #
                        #------------------------------------------------------#
                        # Place all rlogins to root on top. Then add the rest. #
                        # Begin with today's.                                  #
                        #------------------------------------------------------#
                        last | $AWK -v sp="$sp" -v Mon_dd="$_RRL_Mmm_dd" \
                          'match($0,Mon_dd) &&   /^root/ {print sp""$0}' > $tmpwrk1

                        last | $AWK -v sp="$sp" -v Mon_dd="$_RRL_Mmm_dd" \
                          'match($0,Mon_dd) && ! /^root/ {print sp""$0}' > $tmpwrk2

                        #------------------------------------------------------#
                        # Now do the same for previous days.                   #
                        #------------------------------------------------------#
                        _RRL_msgs_back=2
                        _RRL_n=1
                        while [ $_RRL_n -lt $_RRL_msgs_back ]
                        do
                           _RRL_yyyymmdd=`$dateplus -$_RRL_n`
                           _RRL_dd=`echo $_RRL_yyyymmdd | cut -c7-8`
                           _RRL_mm=`echo $_RRL_yyyymmdd | cut -c5-6`
                           #-----------------------------------------------------------#
                           # Using a date $msgs_back from today, display 'last' output.#
                           # Awk note: Printf's "+=0" (in the "Mmm[($1+=0)]") strips   #
                           # leading zeros (it can't find Mmm[06]).  The "%2d" right-  #
                           # justifies (padding with spaces) the dd value.             #
                           #-----------------------------------------------------------#
                           _RRL_Mmm_dd=`echo $_RRL_mm $_RRL_dd | $AWK '
                           {
                             split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", Mmm)
                             printf("%s %2d\n", Mmm[($1+=0)], $2)
                           }'`

                           #-------------------------------------------------------#
                           # Place all rlogins to root on top.  Then add the rest. #
                           #-------------------------------------------------------#
                           last | $AWK -v Mon_dd="$_RRL_Mmm_dd" -v sp="$sp" \
                             'match($0,Mon_dd) &&   /^root/ {print sp""$0}' >> $tmpwrk1

                           last | $AWK -v Mon_dd="$_RRL_Mmm_dd" -v sp="$sp" \
                             'match($0,Mon_dd) && ! /^root/ {print sp""$0}' \
                                | sort +0 -1                                >> $tmpwrk2
                           _RRL_n=`expr $_RRL_n + 1`
                        done

                        #------------------------------------------------------#
                        # If they exist, combine $tmpwrk1 and 2 into $tmpwrk.  #
                        # (I'm NOT using MV_EXIT_ERR here because I only want  #
                        # to see errors; not the move command itself.)         #
                        #------------------------------------------------------#
                        if [ -s "$tmpwrk1" ]; then
                           mv $tmpwrk1 $tmpwrk > $tmplog 2>&1
                           _RRL_status=$?
                           if [ $_RRL_status -ne $success ]; then
                              EMAIL_MSG "FATAL ERROR $script_name"         \
                                "${sp}Moving \$tmpwrk1 to $tmpwrk failed!" \
                                "${sp}Status=$_RRL_status.  $script_name terminated."
                              EXIT $failure
                           fi
                        else
                           CP_DEV_NULL_EXIT_ERR $tmpwrk1 $tmpwrk
                        fi

                        if [ -s "$tmpwrk2" ]; then
                           echo ""       >> $tmpwrk
                           cat  $tmpwrk2 >> $tmpwrk
                        fi

                        RM_EXIT_ERR -f $tmpwrk1 $tmpwrk2

                        if [ -s "$tmpwrk" ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Login activity for last $msgs_back days." | $teelog
                           DISPLAY_TMPWRK | $teelog
                        else
                           echo "`date '+%Y-%m-%d %T'`" \
                             "No login activity for last $msgs_back days." | $teelog
                           echo "${sp}$dashes" | $teelog
                        fi
                      } # "_RRL_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      REPORT_SU_TO_ROOT_ACTIVITY() # Report recent su to root activity.      #
                      #----------------------------------------------------------------------#
                      {
                        _RSR_sulog=/var/adm/sulog
                        if [ ! -f "$_RSR_sulog" ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Skipping scan -- No $_RSR_sulog found!" | $teelog
                           echo "${sp}$dashes"                        | $teelog
                           return
                        fi

                        _RSR_tail_n=100 # last 100 lines; report only last 20 'su - root'
                        _RSR_su_n=`tail -$_RSR_tail_n $_RSR_sulog | grep "\-root" | wc -l`
                        if [ $_RSR_su_n -gt 0 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Tail of $_RSR_sulog's 'su' to root follows:" | $teelog
                           tail -$_RSR_tail_n $_RSR_sulog \
                            | $AWK -v sp="$sp" 'BEGIN {p=0;q=20}
                              /-root/ {n++; if (n <= q) print sp""$0}' | sort -r | $teelog
                        else
                           echo "`date '+%Y-%m-%d %T'`"                             \
                             "No su's to root found in the last $_RSR_tail_n lines" \
                             "of $_RSR_sulog." | $teelog
                        fi
                        echo "${sp}$dashes" | $teelog
                      } # "_RSR_" prefix identifies this function's variables.

                      #----------------------------------------------------------------------#
                      ROOT_DASH_I_FILE() # Accidents happen and sometimes root level files   #
                                         # are deleted.  Creating a '/-i' file adds one more #
                                         # layer of protection for securing root files and   #
                                         # saving the kernel from accidental deletion by     #
                                         # causing any errant 'rm' command to treat this     #
                                         # file as rm's interactive confirmation option.     #
                                         # (The file is easily removed with '\rm - -i'.)     #
                      #----------------------------------------------------------------------#
                      {
                        if [ $opt_b -ne 1 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Skipping '/-i' file create/check." | $teelog
                           echo "${sp}$dashes"                   | $teelog
                           return
                        fi

                        if [ ! -f '/-i' ]; then
                           echo "`date '+%Y-%m-%d %T'` Creating '/-i' file." | $teelog
                           echo "Safeguard against removing root-level files" > '/-i'
                        fi
                        CHMOD_EXIT_ERR 0000 '/-i'
                        ls -al '/-i' | sed "s/^/$sp/" | $teelog
                        echo "${sp}$dashes" | $teelog
                      }

                      #----------------------------------------------------------------------#
                      SNAPSHOT_SYSTEM()
                      #----------------------------------------------------------------------#
                      {
                        echo "`date '+%Y-%m-%d %T'` System snapshot." | $teelog
                        echo "${sp}`uname -a`"                        | $teelog
                        echo "${sp}hostid=`/usr/bin/hostid`"          | $teelog
                        echo "${sp}umask=`umask`"                     | $teelog

                        #----------------------------------------#
                        # Run commands specified in $operations. #
                        #----------------------------------------#
                        for _SS_op in $operations
                        do
                           _SS_op_cmdstring=`$AWK -v cmd="$_SS_op" \
                             'BEGIN {
                                      gsub(/_DASH_/," -",cmd)
                                      gsub(/_SP_/  ," " ,cmd)
                                      print cmd
                                    }'`
                           _SS_op_cmd=`echo "$_SS_op_cmdstring" | sed 's/ .*//'`

                           if [ ! -f "$_SS_op_cmd" ]; then
                              echo "`date '+%Y-%m-%d %T'` '$_SS_op_cmd' not found!" \
                               | $teelog
                              echo "${sp}$dashes" | $teelog
                              continue # Iterate for-loop
                           fi

                           if [ ! -x $_SS_op_cmd ]; then
                              echo "`date '+%Y-%m-%d %T'` '$_SS_op_cmd' not executable!" \
                               | $teelog
                              echo "${sp}`ls -alL $_SS_op_cmd`" | $teelog
                              echo "${sp}$dashes"               | $teelog
                              continue # Iterate for-loop
                           fi

                           #-----------------------------------------------------------#
                           # Since janitor is run by root, we will not run any command #
                           # that is world-writable.  Moreover, such a command is      #
                           # reported to support personnel.                            #
                           #-----------------------------------------------------------#
                           ls -alL $_SS_op_cmd \
                             | $AWK '{if (substr($1,9,1) == "w") exit 1; else exit 0}'
                           if [ $? -eq 1 ]; then
                              EMAIL_MSG "WARNING $script_name"                           \
                                "${sp}Skipping '$_SS_op_cmd' -- command world-writable!" \
                                "${sp}`ls -alL $_SS_op_cmd`"
                              echo "${sp}$dashes" | $teelog
                              continue # Iterate for-loop
                           fi

                           echo "`date '+%Y-%m-%d %T'` Running '$_SS_op_cmdstring'" | $teelog

                           eval $_SS_op_cmdstring > $stdout 2> $stderr
                           _SS_status=$?

                           [ -s "$stderr" ] && sed "s/^/$stderr_sp/" $stderr | $teelog
                           [ -s "$stdout" ] && sed "s/^/$sp/"        $stdout | $teelog

                           echo "`date '+%Y-%m-%d %T'`"                               \
                             "'$_SS_op_cmdstring' completed with $_SS_status status." \
                               | $teelog
                           echo "${sp}$dashes" | $teelog
                        done # for _SS_op in $operations
                      } # "_SS_" prefix identifies this function's variables.


                      #======================================================================#
                      #                     I N I T I A L I Z A T I O N                      #
                      #======================================================================#

                        #------------------------------------------------------------------#
                        # The following is an attempt to extract the path to our           #
                        # $par_file.  Under interactive and cron execution (not "at"       #
                        # execution), this works fine.  We want the path for those cases   #
                        # when this script is run from a directory other than this one.    #
                        # This does not, however, work during batch (at) execution, for    #
                        # there $0 is always /bin/sh.  I haven't figured a way around      #
                        # that problem yet.                                                #
                        #------------------------------------------------------------------#
                        [ $0 = "/bin/sh" -o `dirname $0` = "." ] \
                          && script_home=`pwd` || script_home=`dirname $0`

                        #----------------------------------------------------#
                        # Command line options come before other arguments.  #
                        #----------------------------------------------------#
                        opt_b=0; opt_m=0
                        opt_c=0; opt_n=0
                        opt_g=0; opt_r=0
                        opt_h=0; opt_s=0
                        opt_H=0; opt_T=0
                        opt_h=0; opt_t=0
                        opt_i=0; opt_v=0
                        opt_l=0; opt_w=0

                        invalid_opt=0

                        GO_root=$tmp/$name_root"_"$LOGNAME"_GO_err"
                        GO_err=$GO_root"."$Xtimestamp
                        GO_opts='bcgHhilmnrsTtvw'
                        while getopts $GO_opts GO_opt 2> $GO_err
                        do
                           case $GO_opt in
                              b ) opt_b=1;;
                              c ) opt_c=1;;
                              g ) opt_g=1;;
                              H ) opt_H=1;;
                              h ) opt_h=1;;
                              i ) opt_i=1;;
                              l ) opt_l=1;;
                              m ) opt_m=1;;
                              n ) opt_n=1;;
                              r ) opt_r=1;;
                              s ) opt_s=1;;
                              T ) opt_T=1;;
                              t ) opt_t=1;;
                              v ) opt_v=1; verbose=1;;
                              w ) opt_w=1;;
                             \? ) echo "$script_name Invalid Option: $GO_opt" \
                                       "-`sed 's/^.*-- //' $GO_err`"
                                  invalid_opt=1;;
                           esac
                        done
                        shift `expr $OPTIND - 1` # Shift past options to remaining args

                        #------------------------------------------------------------#
                        # Must reset this dog if getopts is apt to be called again   #
                        OPTIND=1 # (try finding this fact documented anywhere else). #
                        #------------------------------------------------------------#
                        [ ."$GO_root" != . ] && $rm -f $GO_root* > /dev/null 2>&1

                        cleanup_files="$log $stdout_root $stderr_root $tmpwrk_root"
                        cleanup_files="$cleanup_files $tmplog_root $mailmsg_root"
                        for file in $cleanup_files
                        do
                           [ -f "$file" ] && chmod 0640 $file
                        done

                        #--------------------------------------------------------------#
                        # Check for presence of parameter and master parameter files.  #
                        # While we're at it, check their file permissions as well.     #
                        #--------------------------------------------------------------#
                        parfile=$script_home/$name_root.par
                        parfile_master=$script_home/$name_root.master_par
                        parfile_perms="0644"
                        for file in $parfile_master $parfile
                        do
                           if [ ! -f "$file" ]; then               # If $file is missing ..
                              if [ $file = $parfile_master ]; then # If it's the master file
                                 $ECHO "$prelims" 1>&2
                                 EMAIL_MSG "FATAL ERROR $script_name" \
                                   "Unable to locate '$file'!  $script_name terminated."
                                 EXIT 1 # We MUST at least have the master parameter file.
                              else # Missing file is the working, janitor.par file.
                                 prelims="$prelims\n`date '+%Y-%m-%d %T'` Unable to locate $file!"
                                 prelims="$prelims\n${sp}Creating temporary (dummy) par file."
                                 TOUCH_EXIT_ERR $file
                                 continue # Iterate for-loop--don't care about permissions.
                              fi
                           fi

                           curr_perms=`GET_FILE_PERMS $file`
                           status=$?
                           if [ $status -eq 0 ]; then
                              if [ $curr_perms -ne $parfile_perms ]; then
                                 ls_parfile=`ls -al $file | sed 's/  */ /g'`
                                 CHMOD_EXIT_ERR $parfile_perms "$file"
                                 EMAIL_MSG "WARNING $script_name $args"      \
                                   "${sp}$file perms ($curr_perms) wrong!"   \
                                   "${sp}$dashes"                            \
                                   "${sp}$ls_parfile"                        \
                                   "${sp}$dashes"                            \
                                   "FILE=$file"                              \
                                   "${sp}$dashes"                            \
                                   "${sp}Resetting perms to $parfile_perms." \
                                   "${sp}$dashes"                            \
                                   "${sp}`ls -al $file | sed 's/  */ /g'`"
                              fi
                           else
                              $ECHO "$prelims" 1>&2
                              EMAIL_MSG "FATAL ERROR $script_name"              \
                                   "${sp}Unable to get $file file permissions!" \
                                   "${sp}$script_name terminated."
                              EXIT 1
                           fi
                        done # for file in $parfile $parfile_master

                        #----------------------------------------------------------#
                        # Compare timestamp lines in janitor parameter and master  #
                        # parameter files, creating new parameter file from master #
                        # if the timestamps differ.                                #
                        #----------------------------------------------------------#
                        CHECK_PARFILE_FOR_UPDATES # ()

                        #------------------------------------------------------------------#
                        # Reaching this point (not having exited because of a fatal error  #
                        # already) means that our parameter file exists and its perms are  #
                        # [now, at least] intact.  Read and parse parameter file variables.#
                        #------------------------------------------------------------------#
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Assign $parfile parameters."

                        working_dir=`       PARSE_PARAMETERS WORKING_DIR  $parfile`;status=$?
                        log_dir=`           PARSE_PARAMETERS LOG_DIR      $parfile`;status=`expr $status + $?`
                        tmp=`               PARSE_PARAMETERS TMP          $parfile`;status=`expr $status + $?`
                        support=`           PARSE_PARAMETERS SUPPORT      $parfile`;status=`expr $status + $?`
                        active_status_file=`PARSE_PARAMETERS STATUS_FILE  $parfile`;status=`expr $status + $?`
                        keep_logs=`         PARSE_PARAMETERS KEEP_LOGS    $parfile`;status=`expr $status + $?`
                        max_proc_time=`     PARSE_PARAMETERS FIND_MAX_TM  $parfile`;status=`expr $status + $?`
                        rhosts_files=`      PARSE_PARAMETERS RHOSTS_FILES $parfile`;status=`expr $status + $?`
                        perm_600_files=`    PARSE_PARAMETERS 0600_PERMS   $parfile`;status=`expr $status + $?`
                        mail_dir=`          PARSE_PARAMETERS MAIL_DIR     $parfile`;status=`expr $status + $?`
                        file_perms=`        PARSE_PARAMETERS FILE_PERMS   $parfile`;status=`expr $status + $?`
                        ww_dirs=`           PARSE_PARAMETERS WW_DIRS      $parfile`;status=`expr $status + $?`
                        ww_30_dirs=`        PARSE_PARAMETERS WW_30_DIRS   $parfile`;status=`expr $status + $?`
                        ww_excl_dirs=`      PARSE_PARAMETERS WW_EXCL_DIRS $parfile`;status=`expr $status + $?`
                        mtime=`             PARSE_PARAMETERS MTIME        $parfile`;status=`expr $status + $?`
                        old_core=`          PARSE_PARAMETERS OLD_CORE     $parfile`;status=`expr $status + $?`
                        msgs_back=`         PARSE_PARAMETERS MSGS_BACK    $parfile`;status=`expr $status + $?`
                        ps_opts=`           PARSE_PARAMETERS PS_OPTS      $parfile`;status=`expr $status + $?`
                        cron_demon=`        PARSE_PARAMETERS CRON_DEMON   $parfile`;status=`expr $status + $?`
                        cron_stop=`         PARSE_PARAMETERS CRON_STOP    $parfile`;status=`expr $status + $?`
                        cron_start=`        PARSE_PARAMETERS CRON_START   $parfile`;status=`expr $status + $?`
                        cronlog=`           PARSE_PARAMETERS CRONLOG      $parfile`;status=`expr $status + $?`
                        cronlog_size=`      PARSE_PARAMETERS CRONLOG_SIZE $parfile`;status=`expr $status + $?`
                        cronlog_num=`       PARSE_PARAMETERS CRONLOG_NUM  $parfile`;status=`expr $status + $?`
                        wtmp_dir=`          PARSE_PARAMETERS WTMP_DIR     $parfile`;status=`expr $status + $?`
                        wtmp_size=`         PARSE_PARAMETERS WTMP_SIZE    $parfile`;status=`expr $status + $?`
                        wtmp_num=`          PARSE_PARAMETERS WTMP_NUM     $parfile`;status=`expr $status + $?`
                        syslog_dir=`        PARSE_PARAMETERS SYSLOG_DIR   $parfile`;status=`expr $status + $?`
                        syslogs=`           PARSE_PARAMETERS SYSLOGS      $parfile`;status=`expr $status + $?`
                        logins=`            PARSE_PARAMETERS LOGINS       $parfile`;status=`expr $status + $?`
                        messages=`          PARSE_PARAMETERS MESSAGES     $parfile`;status=`expr $status + $?`
                        exclude_fs=`        PARSE_PARAMETERS EXCLUDE_FS   $parfile`;status=`expr $status + $?`
                        operations=`        PARSE_PARAMETERS OPERATIONS   $parfile`;status=`expr $status + $?`

                        [ $opt_T -eq 1 ] && support="Bob@OrlandoKuntao.com"
                        notify="$support"

                        #------------------------------------------------------#
                        # If anything fails to parse, fuss about it and exit.  #
                        #------------------------------------------------------#
                        if [ $status -ne 0 ]; then
                           syslog_msg1="Parameter parsing problem (status=$status)."
                           syslog_msg2="$script_name '$args' ($$) terminated."
                           $ECHO "$prelims" 1>&2

                           subject="FATAL ERROR $HOST: SHLIB PARSE Failure"
                           msg="$syslog_msg1\n$syslog_msg2"
                           MAIL_ERROR

                           if [ $opt_l = 1 -a ."$TERM" = . ]; then
                              logger -p "user.emerg" -t "$USER[$$]_EMER" \
                                "$script_name: $syslog_msg1 $syslog_msg2" 1>&2
                           fi
                           exit 1
                        fi

                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Assignment complete."

                        #----------------------------------------------------------------#
                        # If our log already has something in it.  If it does, then this #
                        # is NOT our first run today.  (We'll use this indicator later   #
                        # to see if we prune the logs or no.)                            #
                        #----------------------------------------------------------------#
                        [ -s "$log" ] && first_run=0 || first_run=1

                        #------------------------------------------------#
                        # If the user wants help, find the documentation #
                        # section and print everything from there down.  #
                        #------------------------------------------------#
                        if [ $opt_H -eq 1 ]; then
                           SHOW_DOCUMENTATION
                           exit $failure
                        elif [ $# -gt 0 -o $opt_h -eq 1 -o $invalid_opt -eq 1 ]; then
                           #------------------------------------#
                           # Showem basic command usage/syntax. #
                           #------------------------------------#
                           echo ""                                                      1>&2
                          $ECHO " Name: $script_name (v%I%)\n"                          1>&2
                           echo "Usage: $script_name -$GO_opts"                         1>&2
                           echo "          -b = Broken symbolic link cleanup."          1>&2
                           echo "          -c = Change errant file permissions."        1>&2
                           echo "          -g = Ensures root ownership of ./gnupg"      1>&2
                           echo "               and 4755 permissions for gpg program."  1>&2
                           echo "          -H = Detailed process documentation."        1>&2
                           echo "          -h = Usage brief."                           1>&2
                           echo "          -i = Install '-i' file in root filesystem."  1>&2
                           echo "          -n = Display contents of .netrc files."      1>&2
                           echo "          -m = Mail SUID scripts found notification."  1>&2
                           echo "          -r = Rollover cron and wtmp logs."           1>&2
                           echo "          -s = Scan and list tail of syslogs."         1>&2
                           echo "          -T = Test mode (notify Bob Orlando only)"    1>&2
                           echo "          -t = List old files in /tmp."                1>&2
                           echo "          -v = Verbose mode (somewhat nosier output)." 1>&2
                           echo "          -w = Report all world-writable files."       1>&2
                           echo ""                                                      1>&2
                           echo "Purpose: Perform various SysAdmin functions."          1>&2
                           echo ""                                                      1>&2
                           exit $failure
                        fi

                        #----------------------------------------------------------------#
                        # If our host name is among WW_30_DIRS parameters (myhost:/home),#
                        # then isolate the directory and remove that directory from the  #
                        # directory list in our WW_DIRS parameter.                       #
                        #----------------------------------------------------------------#
                        if [ ."$ww_30_dirs" = . ]; then
                         # Note: $host in Awk script below must be lowercase (not $HOST).
                           ww_30_dirs=`echo $ww_30_dirs \
                             | $AWK \
                                 'BEGIN {RS=" "; list=""}
                                  /^'$host':/ \
                                  {
                                    sub(/^.*:/,"") # Remove "host:"
                                    gsub(/\n/ ,"") # and newline.
                                    list = list" "$1
                                  }
                                  END {
                                        sub(/^ +/,"",list) # Strip leading whitespace.
                                        print list
                                      }'`

                           ww_dirs=`echo "$ww_dirs" \
                             | $AWK -v ww_30_dirs="$ww_30_dirs" \
                                 'BEGIN {
                                          RS   = " "
                                          list = ""
                                          #-------------------------------#
                                          # Assemble pattern for matching #
                                          #-------------------------------#
                                          gsub(/ +/,"|",ww_30_dirs)     # Insert "or" (stiles)
                                          ww_30_dirs="^("ww_30_dirs")$" # beg- and end-lines
                                        }
                                  $0 !~ ""ww_30_dirs"" \
                                  {
                                    gsub(/\n/,"") # Remove any newlines
                                    list=list" "$0
                                  }
                                  END {
                                        sub(/^ +/,"",list) # Strip leading whitespace.
                                        print list
                                      }'`
                        fi # if [ ."$ww_30_dirs" = . ]; then

                        #----------------------------------------------------------------#
                        # Prefer gzip, but we'll use "compress" if gzip is unavailable.  #
                        #----------------------------------------------------------------#
                        gzip1="/usr/bin/gzip"
                        gzip2="/usr/local/bin/gzip"
                        if [ -x $gzip1 ]; then
                           compress=$gzip1
                           suffix=".gz"
                        elif [ -x $gzip2 ]; then
                           compress=$gzip2
                           suffix=".gz"
                        else
                           compress="$bin_dir/compress"
                           suffix=".Z"
                        fi


                        #------------------------------------------------------------------#
                        # Insure all the critical variables just taken from parfile are    #
                        # assigned. If any are unassigned, then fuss at the user and exit. #
                        # ** Be sure they DO NOT HAVE dollar-signs ($) in front of'em.  ** #
                        # **         Only '$variables' may have the dollar-sign.        ** #
                        #------------------------------------------------------------------#
                        variables="working_dir log_dir tmp notify active_status_file"
                        variables="$variables parfile parfile_master ctlfile" ## T E S T ##
                        variables="$variables rhosts_files perm_600_files mail_dir"
                        variables="$variables file_perms ww_dirs ww_excl_dirs ps_opts"
                        variables="$variables cron_demon cron_stop cron_start cronlog"
                        variables="$variables wtmp_dir syslog_dir syslogs logins messages"
                        variables="$variables compress"
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Verify critical variables."
                        #--------------------------------------------------------------#
                        # operations and ww_30_vars are not verified because they are  #
                        # strictly optional parameters.                                #
                        #--------------------------------------------------------------#
                        VERIFY_VARS $variables # Exits on error

                        variables="args $variables operations exclude_fs ww_30_dirs"

                        num_variables="keep_logs max_proc_time msgs_back mtime old_core"
                        num_variables="$num_variables cronlog_size cronlog_num"
                        num_variables="$num_variables wtmp_size wtmp_num"
                        num_variables="$num_variables opt_b opt_c opt_H opt_h opt_i opt_l"
                        num_variables="$num_variables opt_m opt_n opt_r opt_s opt_T opt_t"
                        num_variables="$num_variables opt_v opt_w"
                        VERIFY_NUM_VARS $num_variables # Exits on error
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Verification complete."

                        #--------------------------------------------------------------#
                        # Change multiple slashes to single, forcing a trailing slash. #
                        # (I don't usually do it this way, but it resolves problems    #
                        # // problems that arise when / is the home directory.)        #
                        #--------------------------------------------------------------#
                        wtmp_dir=`   echo "$wtmp_dir"    | sed 's|//.*|/|g'`
                        working_dir=`echo "$working_dir" | sed 's|//.*|/|g'`
                        log_dir=`    echo "$log_dir"     | sed 's|//.*|/|g'`
                        tmp=`        echo "$tmp"         | sed 's|//.*|/|g'`
                        syslog_dir=` echo "$syslog_dir"  | sed 's|//.*|/|g'`

                        #------------------------------------------------------------------#
                        # While we're at it, verify the permissions of our parameter file. #
                        #------------------------------------------------------------------#
                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Verifying $parfile file permissions."
                        pars_perms=`GET_FILE_PERMS $parfile`
                        if [ $parfile_perms -ne $pars_perms ]; then
                           CHMOD_EXIT_ERR $parfile_perms $parfile
                           EMAIL_MSG "WARNING $script_name"                          \
                             "${sp}Parameter file ($parfile) perms are $pars_perms!" \
                             "${sp}They should have been $parfile_perms."            \
                             "${sp}Resetting perms now (check the following 'ls')."  \
                             "${sp}Processing continues."                            \
                             "${sp}$dashes"                                          \
                             "${sp}`ls -al $parfile | sed 's/  */ /g'`"              \
                             "${sp}$dashes"
                        fi

                        prelims="$prelims\n`date '+%Y-%m-%d %T'` Assign additional variables."

                        tmplog_root=$tmp/$name_root"_tl_"$id_hex"."
                        tmplog=${tmplog_root}$Xtimestamp
                        teetmp="tee -ai $tmplog"
                        cleanup_files="$cleanup_files $tmplog_root"
                                                                     #------------------#
                        mailmsg_root=$tmp/$name_root"_m0_"$id_hex"." # EMAIL_MSG        #
                        mailmsg=${mailmsg_root}$Xtimestamp           # uses this file.  #
                        teemail="tee -ai $mailmsg"                   #------------------#
                        cleanup_files="$cleanup_files $mailmsg_root"

                        stdout_root=$tmp/$name_root"_s1_"$id_hex"."
                        stdout=${stdout_root}$Xtimestamp
                        cleanup_files="$cleanup_files $stdout_root"

                        stderr_root=$tmp/$name_root"_s2_"$id_hex"."
                        stderr=${stderr_root}$Xtimestamp
                        cleanup_files="$cleanup_files $stderr_root"

                        tmpwrk_root=$tmp/$name_root"_t0_"$id_hex"."
                        tmpwrk=${tmpwrk_root}$Xtimestamp
                        cleanup_files="$cleanup_files $tmpwrk_root"
                        tmpwrk_sp="             tmpwrk="

                        tmpwrk1_root=$tmp/$name_root"_t1_"$id_hex"." #------------------#
                        tmpwrk1=${tmpwrk1_root}$Xtimestamp           # Add'l work file. #
                        cleanup_files="$cleanup_files $tmpwrk1_root" #------------------#
                        tmpwrk1_sp="            tmpwrk1="

                        tmpwrk2_root=$tmp/$name_root"_t2_"$id_hex"." #------------------#
                        tmpwrk2=${tmpwrk2_root}$Xtimestamp           # And another.     #
                        cleanup_files="$cleanup_files $tmpwrk2_root" #------------------#
                        tmpwrk2_sp="            tmpwrk2="

                        pidfil_root=$tmp/$name_root"_PI_"$id_hex"."
                        pidfil=${pidfil_root}$Xtimestamp
                        cleanup_files="$cleanup_files $pidfil_root"

                        log_root=$log_dir/$name_root"_log"
                        log=$log_root"."$yymmdd
                        teelog="tee -ai $log"

                        notice_list=$working_dir/$name_root.mail_files
                        variables="$variables notice_list"

                        cleanup_files="$cleanup_files $tmp/$name_root"

                        dateplus=$SHBIN/dateplus # For aged dates (figs, if you like)

                        Mmms="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"

                        #--------------------------------------------------------------#
                        # Assign $rhosts_files and convert that list into 'find' args. #
                        #--------------------------------------------------------------#
                         rhost_pr=`$AWK -v hosts_files="$rhosts_files" \
                           'BEGIN \
                            {
                              q = split(hosts_files,files)
                              for (p = 1; p <= q; p++)
                              {
                                if (p > 1)
                                  find_args=find_args" -name \""files[p]"\" -print"
                                else
                                  find_args="-name \""files[p]"\" -print"

                                if (p < q)
                                  find_args=find_args" -o"
                              }
                               print find_args
                            }'`

                        unsafe_n=0 # Unsafe (open invite) rhosts files
                        chmod_m=0  # System files changed
                        chmod_n=0  # User files changed
                        zero_uids=""
                        zero_uid_n=0
                        suid_scripts_n=0
                        su_files_n=0
                        mail_files_n=0
                        wx_files_n=0
                        ww_files_n=0
                        #----------------------------------------------------------------#
                        # Since I use this awk code in a couple of places, the following #
                        # variable assignment saves having it coded multiple times.      #
                        #----------------------------------------------------------------#
                        awk_perms_script='BEGIN \
                                          { new_perms=""
                                            #------------------------------------------#
                                            # For each octet, if the current value is  #
                                            # less desired perm or less than or equal  #
                                            # to zero, then use desired value, else    #
                                            # retain the current permission.           #
                                            #------------------------------------------#
                                            for (i=1;i<=4;i++)
                                            {
                                              c_perm=substr(curr_perms   ,i,1);
                                              d_perm=substr(desired_perms,i,1);
                                              r_perm=c_perm - d_perm;
                                              if (r_perm >= 0)
                                                new_perms=new_perms""d_perm;
                                              else
                                                new_perms=new_perms""c_perm;
                                            }
                                            print new_perms;
                                          }'

                        #------------------------------------------------------------------#
                        # If our log already has something in it, then this is NOT our 1st #
                        # run today.  (We'll use this indicator later to see if we prune   #
                        # the logs or no.)  Since this is an accumulating log, we really   #
                        # only want to view its activity from this operation (skipping any #
                        # previous operatione), which is why we need the last line number. #
                        #------------------------------------------------------------------#
                        if [ -s "$log" ]; then
                           first_run=0
                           log_pointer=`wc -l < $log`
                        else
                           first_run=1
                           log_pointer=1
                        fi

                        #------------------------------------------------------------------#
                        # Now print all the stuff we were saving.  This way, if the user   #
                        # wanted usage brief or documentation, he doesn't see see all the  #
                        # preliminary stuff and mistakenly think he's started the program. #
                        #------------------------------------------------------------------#
                        $ECHO "$prelims" | $teelog

                        #----------------------------------------------------------#
                        # $fs is a critical variable -- exit on assignment failure.#
                        #----------------------------------------------------------#
                        echo "`date '+%Y-%m-%d %T'`" \
                          "Assign file system variable, \$fs." | $teelog
                        fs=`$DF $df_opt|$AWK 'NR > 1 && $NF !~ /\/cdrom|\/proc/ {print $NF}'`
                        if [ $? -ne 0 ]; then
                           echo "`date '+%Y-%m-%d %T'`" \
                             "Assign file system variable failed!  $0 terminated." | $teelog
                           EXIT 1
                        fi

                        echo "`date '+%Y-%m-%d %T'` Variable assignment complete." | $teelog


                      #======================================================================#
                      #                                M A I N                               #
                      #======================================================================#

                        #--------------------------------------------------------------#
                        # If we receive a hangup, interrupt, or are killed  (with the  #
                        # default 'kill' or 'kill 15'), then run TRAP_EXIT().  This is #
                        # important because by exiting gracefully, we cleanup before   #
                        # exiting.                                                     #
                        #--------------------------------------------------------------#
                        n=0
                        for sig in `kill -l`
                        do
                           n=`expr $n + 1`
                           [    ".$sig" = ".EXIT" -o ".$sig" = ".SEGV" \
                             -o ".$sig" = ".CHLD" -o ".$sig" = ".CLD"  \
                             -o ".$sig" = ".TSTP" -o ".$sig" = ".CONT" \
                           ] && continue
                           trap "echo Exit $sig \($n\) 1>&2; \
                                 TERMINATE_SUBPROCESSES; TRAP_EXIT $n" $n
                        done

                        #----------------------------------------------------#
                        # If unable to touch or chmod $log, fuss at the user #
                        # (the function does this via stderr) and exit.      #
                        #----------------------------------------------------#
                        TOUCH_EXIT_ERR_NOMAIL       $log # Touch because we'll append to it.
                        CP_DEV_NULL_EXIT_ERR_NOMAIL $stdout $stderr
                        CP_DEV_NULL_EXIT_ERR        $tmpwrk $tmplog
                        CHMOD_EXIT_ERR_NOMAIL 0600  $log $stdout $stderr \
                                                    $tmpwrk $tmplog $mailmsg

                        echo "`date '+%Y-%m-%d %T'`" \
                          "Begin `uname -n`:$script_name (PID=$$)" | $teelog

                        #------------------------------------#
                        # Display process variables.         #
                        #------------------------------------#
                        echo "`date '+%Y-%m-%d %T'` Listing $script_name variables." | $teelog

                        var_list="bin_dir awk mail df kill rm echo" # Binaries
                        var_list="$var_list fs log teelog stdout stderr mailmsg tmplog"
                        var_list="$var_list tmpwrk tmpwrk1 tmpwrk2"
                        var_list="$var_list dateplus log_pointer"
                        var_list="$var_list rhost_pr script_home"
                        #------------------------------------#
                        # Print a sorted (-s) variable list. #
                        #------------------------------------#
                        PRINT_VARS -s $variables $var_list $num_variables

                        #------------------------------------------------------------------#
                        # If a this script is already running, then don't start a new one. #
                        # However, if $active_status file is more than a day old, then     #
                        # notify support and remove the dog.                               #
                        #                                                                  #
                        # Else, write our current process ID ($$) to $active_status_file   #
                        # (the file is removed on exiting this process via EXIT function). #
                        #------------------------------------------------------------------#
                        if [ ."$active_status_file" != . ]; then
                           active_filename=`basename $active_status_file`
                           find="find $working_dir -name $active_filename -mtime +1 -print"
                           echo "`date '+%Y-%m-%d %T'` $find" | $teelog
                           old_active_file=`$find`
                           if [ ."$old_active_file" != . ]; then
                              EMAIL_MSG "Old Active Status File Found" \
                                "${sp}Found old active status file!"   \
                                "${sp}($old_active_file)"              \
                                "${sp}Removing file and continuing."

                              echo "`date '+%Y-%m-%d %T'`" \
                                "rm -f $active_status_file"     | $teelog
                                 rm -f $active_status_file 2>&1 | $teelog
                           fi
                        fi

                        EXIT_IF_ALREADY_RUNNING

                        ELAPSED_TIME start $program_start # $program_start captured above.

                        #--------------------------#
                        # How long we've been up.  #
                        #--------------------------#
                        /usr/bin/uptime                        \
                          | $AWK -v sp="$sp" -v dashes=$dashes \
                            '{
                               "date \047+%Y-%m-%d %T\047" | getline timestamp
                               uptime=timestamp" Uptime = "$3" "$4" "$5
                               if ($6 ~ /min/) uptime=uptime" "$6
                               sub(/,$/,"",uptime) # Remove any trailing comma
                               print uptime"\n"sp""dashes
                               exit
                             }' | $teelog

                        #--------------------------------------------------------------#
                        # The '()' in the following lines is simply to make it easy to #
                        # find ALL function declaration and function calls.            #
                        #--------------------------------------------------------------#
                        ROOT_DASH_I_FILE                                        # ()
                        CHECK_DEV_NULL_PERMS                                    # ()
                        CHECK_ROOT_DIR_PERMS                                    # ()
                        CHECK_TMP_DIR_PERMS                                     # ()
                        CHECK_VAR_MSGS_PERMS                                    # ()
                        [ $opt_g -eq 1 ] && ENSURE_GNUPG_PERMS                  # ()
                        CHECK_CRITICAL_ID_MAIL                                  # ()
                        CHECK_N_ROLL_WTMP_FILESIZES                             # ()
                        CHECK_N_ROLL_CRON_LOG                                   # ()
                        FIND_AND_CHMOD 0600 $perm_600_files                     # ()
                        EXAMINE_NETRC_FILES                                     # ()
                        EXAMINE_RHOSTS_FILES                                    # ()
                        LIST_SU_FILES                                           # ()
                        CHECK_PASSWD_FOR_UID_0                                  # ()
                        DISPLAY_SETUID_SCRIPTS                                  # ()
                        REPORT_SU_TO_ROOT_ACTIVITY                              # ()
                        REPORT_RECENT_LOGIN_ACTIVITY                            # ()
                        LIST_CORE_DUMP_FILES; [ $? -gt 0 ] && REMOVE_OLD_CORE_DUMPS # ()
                        CHMOD_SPECIFIC_FILES $file_perms                        # ()
                        REMOVE_WORLD_FILE_PERMS            "w" 0003 $ww_dirs    # ()
                        REMOVE_WORLD_FILE_PERMS -m +$mtime "w" 0003 $fs         # () W-execute
                        if [ ."$ww_30_dirs" != . ]; then
                           REMOVE_WORLD_FILE_PERMS -m +30  "w" 0003 $ww_30_dirs # ()
                        fi
                        LIST_WORLD_WX_FILES                                     # ()

                        REMOVE_WORLD_FILE_PERMS            "w" 0002 $ww_dirs    # ()
                        REMOVE_WORLD_FILE_PERMS -m +$mtime "w" 0002 $fs         # () W-write
                        if [ ."$ww_30_dirs" != . ]; then
                           REMOVE_WORLD_FILE_PERMS -m +30  "w" 0002 $ww_30_dirs # ()
                        fi

                        LIST_ALL_WW_FILES                                       # ()
                        BROKEN_SYMBOLIC_LINKS                                   # ()
                        LIST_OLD_TMP_FILES                                      # ()

                        if [ $opt_s -eq 1 ]; then
                           FIND_ERRORS_IN_SYSLOGS                               # ()
                           LAST_20_LINES_SYSLOGS                                # ()
                        fi

                        SNAPSHOT_SYSTEM                                         # ()

                        #----------------------------------------------------------------#
                        # Only on the first run of the day do we prune our process logs. #
                        #----------------------------------------------------------------#
                        [ $first_run -eq 1 ] && PRUNE_FILES $keep_logs $log_root

                        CLEANUP_WORK_FILES $cleanup_files 2>&1 | $teelog

                        #--------------------------------------------------------#
                        elapsed_time=`ELAPSED_TIME stop` # OK, let's clock out.  #
                        #--------------------------------------------------------#

                        unsafe_m=`      printf "%5d" $unsafe_m`
                        unsafe_n=`      printf "%5d" $unsafe_n`
                        zero_uid_n=`    printf "%5d" $zero_uid_n`
                        suid_scripts_n=`printf "%5d" $suid_scripts_n`
                        chmod_m=`       printf "%5d" $chmod_m`
                        chmod_n=`       printf "%5d" $chmod_n`
                        su_files_n=`    printf "%5d" $su_files_n`
                        mail_files_n=`  printf "%5d" $mail_files_n`
                        wx_files_n=`    printf "%5d" $wx_files_n`
                        ww_files_n=`    printf "%5d" $ww_files_n`
                        broken_ln=`     printf "%5d" $broken_ln`

                        if [ ."$_CRC_rollovers" != ."None" ]; then
                           _CRC_rollovers=`echo "$_CRC_rollovers" | sed 's/^None //'`
                        fi
                           _CRC_rollovers="Cron Log Rollovers: $_CRC_rollovers"

                        if [ ."$_CRW_rollovers" != ."None" ]; then
                           _CRW_rollovers=`echo "$_CRW_rollovers" | sed 's/^None //'`
                        fi
                           _CRW_rollovers="WTMP Log Rollovers: $_CRW_rollovers"

                        if [ ."$TERM" = . ]; then
                           sed -n "$log_pointer,$ p" $log > $tmplog
                           EMAIL_MSG "$script_name"                                         \
                               "${sp}$script_name completed in $elapsed_time."              \
                               "${sp}      Search"                                          \
                               "${sp}Count String  Category."                               \
                               "${sp}----- ------- -----------------------------------"     \
                               "${sp}$unsafe_m (_ERF_) Unsafe .rhosts file contents found." \
                               "${sp}$unsafe_n (_FAC_) Unsafe .rhosts file perms found."    \
                               "${sp}$zero_uid_n (_CPU_) Non-root UID=0 found: $zero_uids"  \
                               "${sp}$su_files_n (_LSU_) Executable 'su' files found."      \
                               "${sp}$suid_scripts_n (_DSS_) SUID script(s) found."         \
                               "${sp}$mail_files_n (_CCM_) Critical ID mail files found."   \
                               "${sp}$chmod_m (_CSF_) System file permissions changed."     \
                               "${sp}$chmod_n (_RWP_) User   file permissions changed."     \
                               "${sp}$wx_files_n (_LWX_) World-WX files remain."            \
                               "${sp}$ww_files_n (_LWW_) World-WW files remain."            \
                               "${sp}$broken_ln (_BSL_) $broken_links"                      \
                               "${sp}      (_CRW_) $_CRW_rollovers."                        \
                               "${sp}      (_CRC_) $_CRC_rollovers."                        \
                               "${sp}$dashes"                                               \
                               "NO_LOG"                                                     \
                               "${sp}Log ($log) follows:"                                   \
                               "${sp}$ddashes"                                              \
                               "FILE=$tmplog"
                        else
                           $ECHO "`date '+%Y-%m-%d %T'`"                                    \
                             "$script_name completed in $elapsed_time."                     \
                             "\n${sp}      Search"                                          \
                             "\n${sp}Count String  Category."                               \
                             "\n${sp}----- ------- -----------------------------------"     \
                             "\n${sp}$unsafe_m (_ERF_) Unsafe .rhosts file contents found." \
                             "\n${sp}$unsafe_n (_FAC_) Unsafe .rhosts file perms found."    \
                             "\n${sp}$zero_uid_n (_CPU_) Non-root UID=0 found: $zero_uids"  \
                             "\n${sp}$su_files_n (_LSU_) Executable 'su' files found."      \
                             "\n${sp}$suid_scripts_n (_DSS_) SUID script(s) found."         \
                             "\n${sp}$mail_files_n (_CCM_) Critical ID mail files found."   \
                             "\n${sp}$chmod_m (_CSF_) System file permissions changed."     \
                             "\n${sp}$chmod_n (_RWP_) User   file permissions changed."     \
                             "\n${sp}$wx_files_n (_LWX_) World-WX files remain."            \
                             "\n${sp}$ww_files_n (_LWW_) World-WW files remain."            \
                             "\n${sp}$broken_ln (_BSL_) $broken_links"                      \
                             "\n${sp}      (_CRW_) $_CRW_rollovers."                        \
                             "\n${sp}      (_CRC_) $_CRC_rollovers." | $teelog
                        fi

                        CLEANUP_WORK_FILES $tmplog_root 2>&1 | $teelog

                        TERMINATE_SUBPROCESSES # Just in case we have any hanging around.

                        EXIT $success


                      
                      #======================================================================#
                      #                      D O C U M E N T A T I O N                       #
                      #----------------------------------------------------------------------#
                      #                                                                      #
                      #      Author: Bob Orlando <Bob@OrlandoKuntao.com>                     #
                      #                                                                      #
                      #        Date: June 19, 1995                                           #
                      #                                                                      #
                      #  Program id: janitor.sh                                              #
                      #                                                                      #
                      #       Usage: janitor.sh -bcgHhilmnrsTtvw                             #
                      #                         -b = Broken symbolic link cleanup.           #
                      #                         -c = Change errant file permissions.         #
                      #                         -g = Ensures root ownership of ./gnupg       #
                      #                              and 4755 permissions for gpg program.   #
                      #                         -H = Displays process documentation.         #
                      #                         -h = Displays usage brief.                   #
                      #                         -i = Install '-i' file in root filesystem.   #
                      #                         -l = Also use 'logger' for error reporting.  #
                      #                         -m = Mail SUID scripts found notification.   #
                      #                         -n = Display contents of .netrc files.       #
                      #                         -r = Rollover cron and wtmp logs.            #
                      #                         -s = Scan and list tail of syslogs.          #
                      #                         -T = Test mode (notify Bob Orlando only)     #
                      #                         -t = List old files in /tmp.                 #
                      #                         -v = Verbose mode (somewhat noisier output). #
                      #                         -w = Report all world-writable files.        #
                      #                                                                      #
                      # Code Contrl: aphrodite:~dmc/SCCS.                                    #
                      #                                                                      #
                      #     Purpose: Perform various sysadmin functions.                     #
                      #                                                                      #
                      # Description: Normally called by cron, this script performs the       #
                      #              following:                                              #
                      #                                                                      #
                      #              * Compares timestamps in master parameter file,         #
                      #                janitor.master_par and runtime parameter file,        #
                      #                janitor.par, updating runtime version when the        #
                      #                master is found with a different timestamp.           #
                      #              * Checks /dev/null, / (root directory), /tmp and        #
                      #                /var/tmp directory, and /var/adm/messages* file       #
                      #                permissions.                                          #
                      #              * Optionally ensures gpg file permissions are 4755.     #
                      #              * Reports mail found for system IDs such as root,       #
                      #                bin, daemon, lp, etc.                                 #
                      #              * Informs when cronlog and wtmp* file sizes exceed      #
                      #                sizes specified in the program's parameter file       #
                      #                and optionally rolls over these files when they       #
                      #                exceed the size specified in the program's            #
                      #                parameter file (at this time this option is used      #
                      #                on all of the hosts under DMC monitoring).            #
                      #              * Scans and reports .rhosts files that pose security    #
                      #                risks (e.g. files having '+' or '+ +' entries         #
                      #                in them, as well as having file permissions other     #
                      #                than 0600).  Also displays contents of all .rhosts    #
                      #                and hosts.equiv files.                                #
                      #              * Changes .forward and .netrc file permissions to       #
                      #                0600.                                                 #
                      #              * Displays recent 'su' to root and rlogin activity.     #
                      #              * Reports and changes specific files (listed in         #
                      #                janitor.perms) that have other than the desired       #
                      #                or recommended permissions.                           #
                      #              * Reports files having world-write and                  #
                      #                world-write-execute permissions.  Optionally, WW      #
                      #                and WX files in home can have the WW permission       #
                      #                removed from files in /home (at this time, this       #
                      #                option is used on all of the hosts under DMC          #
                      #                monitoring).                                          #
                      #              * Lists all core files found and removes those not      #
                      #                modified in $old_core days.                           #
                      #              * Lists /tmp files not accessed in last 7 days.         #
                      #              * Reports recent "errors" from /var/adm/messages*       #
                      #                and /var/log/syslog* files.                           #
                      #              * Report UIDs in /etc/passwd that have a UID of         #
                      #                zero but are some other ID other than root.           #
                      #                (It reported smtp as being one such user.)            #
                      #              * Report all executable root-SUID files. For example,   #
                      #                on ibesdev, in addition to /usr/bin/su, we found      #
                      #                /platform/sun4u/kernel/drv/su (-rwxr-xr-x 1 root sys  #
                      #                26552 Jul 15 1997 /platform/sun4u/kernel/drv/su).     #
                      #              * Optionally, create (if absent) a '-i' file in root.   #
                      #                Such a file adds one more layer of protection for     #
                      #                securing root files and saving the kernel from        #
                      #                accidental deletion by causing errant interactive     #
                      #                'rm' commands in root to treat this file as rm's      #
                      #                interactive confirmation option.  This file only      #
                      #                affects interactive "removes" and is easily removed   #
                      #                with '\rm - -i', should globbing be absolutely        #
                      #                necessary.                                            #
                      #              * Displays system snapshot (e.g. uname -a, hostid,      #
                      #                umask, and command operations like df -lk, mount,     #
                      #                and others specified in the OPERATIONS parameter).    #
                      #                This snapshot can handle most any command line        #
                      #                operation.  Here is a sample list:                    #
                      #                                                                      #
                      #                  /usr/sbin/mount -p                                  #
                      #                  /usr/bin/df -lk                                     #
                      #                  /usr/local/etc/prtvtoc.sh # format, prtdiag/prtconf #
                      #                  /usr/sbin/vxprint -l                                #
                      #                  /usr/local/bin/sar.sh                               #
                      #                  /bin/cat /etc/profile                               #
                      #                  /bin/cat /etc/passwd /etc/shadow                    #
                      #                                                                      #
                      #       Files: /usr/local/etc/janitor.par                              #
                      #                 = CRITICAL runtime parameter file.  Won't run home   #
                      #                   without it.                                        #
                      #              /usr/local/etc/janitor.master_par                       #
                      #                 = CRITICAL parameter file master.  Won't run home    #
                      #                   without it.                                        #
                      #              /usr/local/etc/janitor.fileperms                        #
                      #                 = List of specific files and their desired perms.    #
                      #              /var/logs/janitor_log.yymmdd                            #
                      #                 = Process log file pruned to $keep_logs.             #
                      #                                                                      #
                      #   Externals: /usr/local/bin/dateplus                                 #
                      #                 = Returns aged dates for looking back through        #
                      #                   message logs.                                      #
                      #                                                                      #
                      #       Notes: You will find numerous lines with '# ()' appended to    #
                      #              them.  This allows location of all function calls       #
                      #              (the function declarations already have '()' -- adding  #
                      #              '# ()' to calls makes it possible to grep all '()' and  #
                      #              see both declarations and calls).                       #
                      #                                                                      #
                      #              You will see many 'find' commands with assassin code    #
                      #              to terminate them if they exceed 5 minutes.  We do not  #
                      #              diagnose the problem, simply terminate the find, report #
                      #              said termination, and continue.                         #
                      #                                                                      #
                      #    Modified: 2006-09-28 Bob Orlando                                  #
                      #                 v2.43 * Migrate from root SCCS ownership to DMC.     #
                      #                                                                      #
                      #              2006-02-02 Bob Orlando                                  #
                      #                 v2.42 * Added the following echo for -T operation in #
                      #                         CHMOD_SPECIFIC_FILES()                       #
                      #                                                                      #
                      #                           [ $verbose -eq 1 ] \                       #
                      #                             && echo "${sp}Checking $_CSF_file" ...   #
                      #                                                                      #
                      #----------------------------------------------------------------------#
            
Artificial Intelligence is no match for natural stupidity.
©Copyright Bob Orlando, 1995-2012
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update: Jan. 17, 2012
by Bob Orlando