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

                PSW_ps="/usr/ucb/ps"            # Default UCB ps
                [ -x "$PSW_ps" ] || PSW_ps="ps" # Pathed ps unless /usr/ucb/ps exists
                PSW_ps="$PSW_ps -auxww"         # Add the options

                #------------------------------#
                # Parse any function options.  #
                #------------------------------#
                PSW_case="respect" # Respect case (the default) in pattern match.
                PSW_rs="e"         # Record separator ('e' is the default)
                while getopts ir: PSW_opt 2> /dev/null
                do
                   case $PSW_opt in
                      i ) PSW_case="ignore";;
                      r ) PSW_rs="$OPTARG";;
                      * ) ;;
                   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 that little gem documented elsewhere). #
                #--------------------------------------------------------------#

                if [ $# -gt 0 ]; then
                   $PSW_ps | $AWK -v str="$*"         \
                                  -v case="$PSW_case" \
                                  -v rs="$PSW_rs"     \
                     'BEGIN {
                              RS       = rs     # Since "e" is the most common
                              n        = 0      # letter in English, it is our
                              proc     = ""     # default record separator (RS).
                              pids     = ""
                              lines[0] = 0
                              if (case == "ignore") str = tolower(str)
                            }
                      { ##  M A I N  ##
                        gsub(/[\t ]+\n/,"\n",$0)# Squeeze tabs and blanks
                        if ($0 ~ /\n/)          # Any newlines in our ps chunk?
                        {
                          lines[0] = split($0,lines,"\n")
                          for (i=1; i <= lines[0]; i++)
                          {
                            if (i == 1)         # On the 1st line in lines[]:
                            {                   # If proc variable
                              if (proc == "")   # is empty, then
                                proc = lines[1] #  assign lines[1] to it.
                              else              # Else finish assembly of proc
                                proc = proc""RS""lines[1] # (our reassembled ps line).
                                                # If proc happens to be our
                              print_if_match()  # target, print it.
                              continue          # Regardless, iterate our for-loop.
                            }
                                                # All lines following the first are
                            proc = lines[i]     # automagically assigned to proc.
                                                # If it is not the last line (we
                            if (i < lines[0])   # already know it is not the first)
                            {                   # and if it happens to be our target
                              print_if_match()  # process, we print it and iterate
                              continue          # our loop.  Otherwise, it must be
                            }                   # the last line in the array, and
                            next                # since it is already assigned to
                          } # for (i=1; i ...   # proc, we just break out and get
                        } # if ($0 ~ /\n/)      # our next chunk of "ps" output.

                        proc = proc""RS""$0
                      } ##  M A I N  ##

                      #---------------------------------------------------------#
                      function print_if_match()
                      #---------------------------------------------------------#
                      {
                        psline = proc
                        #-----------------------------------------------#
                        # For lowercase, we must feed tolower() parsed  #
                        # output so as to aviod its size limitation.    #
                        #-----------------------------------------------#
                        if (case == "ignore")
                        {
                          line_len = length(proc)
                          if (line_len > 2048)
                          {
                            proc = ""
                            for (i=1; i<=line_len; i+=2048)
                              proc = proc""tolower(substr(psline,i,2048))

                            sub(/ +$/,"",proc) # Squeeze tabs and blanks
                          }
                          else
                          {
                            proc = tolower(proc)
                          }
                        } # if (case == "ignore")

                        if (match(proc,str) && ! match(proc,/awk -v str=/))
                        {
                          print "PS="psline | "cat 1>&2"     # Print real ps line to stderr
                          pid = substr(proc,1,50)            # Isolate PID
                          sub(/^[A-Za-z0-9_]+[\t ]+/,"",pid) # Drop 1st word and all
                          sub(/[\t ].*/,"",pid)              # following 2nd (leaves PID)
                          pids = pids" "pid                  # Add PID to list.
                          n++                                # Num of procs found.
                        }
                        proc = ""
                      } # function print_if_match()

                      END {
                            sub(/^ /,"",pids)
                            print pids
                            n = (n < 254) ? n : 254
                            exit n # Return the number of processes found.
                          }'
                   return $?
                else # Caller provided no target ps string
                   if [ .${SHLIB} = . ]; then SHLIB=/usr/local/scripts; export SHLIB; fi
                   #-------------------------------------------------------------#
                   # If the following variables are not set, use these defaults. #
                   #-------------------------------------------------------------#
                   : ${script_name:=`basename $0`}
                   : ${sp:="                    "}

                   . $SHLIB/email_msg.sh # Calls $SHLIB/exit.sh
                   if [ $# -lt 1 ]; then
                      EMAIL_MSG "ERROR: $script_name($PSW_name)"           \
                        "${sp}Insufficient args!"                          \
                        "${sp}Usage: $PSW_name -i -r RS_char -- ps_string" \
                        "${sp}Function terminated--processing continues."
                   fi
                   return 255
                fi
              } # "PSW_" prefix identifies this function's variables.
              fi

              #======================================================================#
              #                       D O C U M E N T A T I O N                      #
              #======================================================================#
              #                                                                      #
              #      Author: Bob Orlando                                             #
              #                                                                      #
              #        Date: August 11, 2004                                         #
              #                                                                      #
              #  Program ID: ps_auxww.sh                                             #
              #                                                                      #
              #       Usage: PS_AUXWW -i -r RS_char -- ps_target                     #
              #                                                                      #
              #                       -i = Ignore case when matching pattern         #
              #                       -r = Use the following character for the       #
              #                            record separator (defaults to 'e').       #
              #                       -- = Stops getopts processing should the       #
              #                            ps_target begin with a hyphen.            #
              #                ps_target = Process string we seek from ps output.    #
              #                                                                      #
              #     Purpose: Use UCB 'ps -auxww' to list processes in the process    #
              #              queue, displaying those lines matching our ps target.   #
              #                                                                      #
              # Description: Devoid of options -i and -r, this program uses UCB's    #
              #              ps with options -auxww to search the process queue and  #
              #              display those ps lines (respecting case) that match our #
              #              target string.  The return status indicates the number  #
              #              of processes found (see "Exit Status:" below). A PID    #
              #              list is displayed via stdout.  The matching ps lines    #
              #              are displayed via stderr.  The caller is expected to    #
              #              redirect/capture that output as needed.                 #
              #                                                                      #
              #              AWK is used as the pattern matching engine because      #
              #              some Unix hosts lack Perl.  However, AWK's buffer       #
              #              limitation made processing long ps lines problematic.   #
              #              UCB 'ps -auxww' output can be VERY long (longer than    #
              #              either sed or AWK can handle), so I use the letter 'e'  #
              #              (the default) as the record separator (RS).  As the     #
              #              most common letter in English, using it as the RS       #
              #              allows the program to ingest all the data in smaller    #
              #              chunks, before reassembling the data into a single      #
              #              line when we encounter a newline.                       #
              #                                                                      #
              #    Examples: After sourcing the script to load the function (i.e.    #
              #              ". ./ps_auxww.sh"), you can run PS_AUXWW as follows:    #
              #                                                                      #
              #              1. Find jsm-ruleseng in process queue.  PIDs are        #
              #                 displayed in stdout, while the actual ps strings     #
              #                 are displayed via stderr.                            #
              #                                                                      #
              #                   PS_AUXWW jsm-ruleseng                              #
              #                                                                      #
              #              2. Find jsm-ruleseng, printing PIDs, discarding         #
              #                 any ps line output by redirecting stderr to          #
              #                 to /dev/null.                                        #
              #                                                                      #
              #                   PS_AUXWW jsm-ruleseng 2> /dev/null                 #
              #                                                                      #
              #              3. Find jsm-ruleseng assigning ps output (stderr)       #
              #                 to $pss and redirecting PIDs (stdout) to /dev/null.  #
              #                                                                      #
              #                   pss=`PS_AUXWW "jsm-ruleseng" 2>&1 > /dev/null`     #
              #                                                                      #
              #              4. Find jsm-ruleseng assigning PID list to $pids        #
              #                 and redirecting any ps line output to a file.        #
              #                                                                      #
              #                   pids=`PS_AUXWW "jsm-ruleseng" 2> /tmp/stderr`      #
              #                                                                      #
              #              5. Return only the number of processes found            #
              #                 (see "Exit Status:" below).                          #
              #                                                                      #
              #                   PS_AUXWW jsm-ruleseng > /dev/null 2>&1             #
              #                   status=$?                                          #
              #                                                                      #
              #              6. Find "-bg black -fg Green" (Note the "--"            #
              #                 to end option processing before the string.)         #
              #                                                                      #
              #                   PS_AUXWW -- -bg black -fg Green                    #
              #                                                                      #
              #              7. Find "-bg black -fg Green" ignoring case.            #
              #                                                                      #
              #                   PS_AUXWW -i -- -bg black -fg Green                 #
              #                                                                      #
              #              8. Find "-bg black -fg Green" using the second most     #
              #                 frequently found letter in the English language.     #
              #                                                                      #
              #                   PS_AUXWW -r "t" -- -bg black -fg Green             #
              #                   PS_AUXWW -r t -- -bg black -fg Green # Ditto       #
              #                                                                      #
              #              9. Alias PS_AUXWW function as "pswa" so we can          #
              #                 search the process queue, ignoring case.             #
              #                                                                      #
              #                   . ./ps_auxww.sh # Source the PSWA function.        #
              #                   pswa () {PS_AUXWW '-i' "$@" 2>&1 1> /dev/null ; }  #
              #                                                                      #
              #                 Calling PS_AUXWW in this fashion (as a function      #
              #                 instead of an alias) makes alias functionality       #
              #                 available regardless of shell.                       #
              #                                                                      #
              #     Globals: "PSW_" prefix identifies local function variables.      #
              #                                                                      #
              # Exit Status: Returns the number of matching process lines in our     #
              #              status as follows:                                      #
              #                                                                      #
              #                0-253 = Actual number of processes found.             #
              #                  254 = Indicates more than 253 processes found.      #
              #                  255 = ERROR: Caller provided no target ps string.   #
              #                                                                      #
              #       Calls: EMAIL_MSG library function.                             #
              #                                                                      #
              #       Notes: ....................................................    #
              #              ....................................................    #
              #                                                                      #
              #    Modified: 20yy-mm-dd Bob Orlando                                  #
              #                 v1.2  * Move display of stdout (pid list) to END     #
              #                         section (instead of displaying them as we    #
              #                         get them).                                   #
              #                       * Expand documentation to include an           #
              #                         aliasing example.                            #
              #                                                                      #
              #              2004-09-18 Bob Orlando                                  #
              #                 v1.1  * Initial release.                             #
              #                                                                      #
              #----------------------------------------------------------------------#
            
Artificial Intelligence is no match for natural stupidity.
©Copyright Bob Orlando, 2004-2011
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update: Jan. 26, 2011
by Bob Orlando