#!/bin/ksh

#
#@(#) File:    showstat.sh
#@(#) Version: 1.0.0
#@(#) History: 
#@(#)     2016-11-17 : Roger Leuckie : Created
#

trap "" 1 3
trap "fCleanup 1 STOPPED_BY_USER" 2

export LANG=C
export LC_ALL=C

export sBaseDir="${0%/*}"
export sBaseName="${0##*/}"
if [ x"${sBaseDir}" = x"${sBaseName}" ]; then
        sBaseDir="${PWD}"
fi
sCurDir="${PWD}"
cd "${sBaseDir}"
sBaseDir="${PWD}"
cd "${sCurDir}"

export PATH="${sBaseDir}:${PATH}"

sPIDpattern=""	 		 		 		 		 	# -p all | -p "pid|pid|pid"

(( bShowHelp = 0 ))
(( bShowFilterHelp = 0 ))

sTYPEpattern=""	# -t all | -t "fifo|file|dir|unix|net" or -t "semaphore|sharedmem"

sNAMEpattern=""	 		 		 		 		 	# -n all | -n "name1|name2|name3|...|..."

sUSERpattern=""	 		 		 		 		 	# -u all | -u "user1|user2|user3"

(( bUSEfile	= 0 ))

(( bAcceptedLicense	 	= 0 ))	 		 		 	# -L a

(( bShowInterval = 0 ))


(( bReportBasic	 		 	= 0 ))	 		 		 	# -r b
(( bReportDetails	 	= 0 ))	 		 		 	# -r d
(( bReportTrend	 		 	= 0 ))	 		 		 	# -r T
(( bReportTrendAll	 	= 0 ))	 		 		 	# -r TA
(( bReportTime	 		 	= 0 ))	 		 		 	# -r t
(( bReportFlags	 		 	= 0 ))	 		 		 	# -r f

typeset -i iIntervalDelay=0	 		 		 	# -i "interval count"
typeset -i iIntervalMax=0
(( iDefaultDelay = 60 ))

sDEFAULTcmd="lsof"

sMONITORcmd=""	 		 		 		 		 	# -c ${sDEFAULTcmd}_command

sMONITORfile=""	 		 		 		 		 	# -f ${sDEFAULTcmd}_file

sSTOPfile="${0}.stop"						# -S stop file

sREPORTfile=""	 		 		 		 		 	# -o output
(( bDoOverwriteFiles = 0 ))	 		 		 	# -O

sLOGfile=""	 		 		 		 		 	# -l log file

(( bQuietMode = 0 ))	 		 		 		 	# -q
(( bDebugMode = 0 ))	 		 		 		 	# -d

(( bRunEXTRAfile = 0 ))

sAWKfilter=""	 	 	 	 	 	 	 # -a awk_filter

sEXTRAfile="${0}.extra"
if [ -f "${sEXTRAfile}" ]; then
	chmod 777 "${sEXTRAfile}" >/dev/null 2>&1
else
	sEXTRAfile=""
fi

fGetTmpFile() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

	 	(( _ct = 1 ))
	 	while [ -n "${aTmpFile[${_ct}]}" ]; do
	 		 	(( _ct = _ct + 1 ))
	 	done

	 	for _sTmpPrefix in "${PWD}/${sBaseName}." "${TMPDIR-:/tmp}/${sBaseName}." "${HOME}/${sBaseName}." "${0}."; do

	 		 	_sTmpFile="${_sTmpPrefix}${RANDOM}${RANDOM}.${LOGNAME}.${_ct}.tmp"
	 		 	if touch "${_sTmpFile}" >/dev/null 2>&1; then
	 		 		 	aTmpFile[${_ct}]="${_sTmpFile}"
	 		 		 	break
	 		 	fi

	 	done
	 	if [ -z "${aTmpFile[${_ct}]}" ]; then
	 		 	echo "[ ERROR ] Unable to create temp files in ${PWD}, ${TMPDIR-:/tmp}, ${HOME}, ${sBaseDir}" >&2
	 		 	fCleanup 1
	 	fi

	 	return ${_ct}
}

fShowLicense() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi
cat << END_OF_LICENSE
----------------------------------------------
 IBM International Program License Agreement
----------------------------------------------

 Part 1 - General Terms
 -----------------------

 PLEASE READ THIS AGREEMENT CAREFULLY BEFORE USING THE PROGRAM. IBM WILL
 ONLY LICENSE THE PROGRAM TO YOU IF YOU FIRST ACCEPT THE TERMS OF THIS
 AGREEMENT BY USING THE PROGRAM. IF YOU DO NOT AGREE TO THE TERMS OF THIS
 AGREEMENT, PROMPTLY NOTIFY THE PROVIDER OF THE PROGRAM AND REQUEST A
 REFUND OF THE AMOUNT YOU PAID.

 The Program is owned by International Business Machines Corporation or
 one of its subsidiaries (IBM) or an IBM supplier, and is copyrighted and
 licensed, not sold.

 IBM grants you a nonexclusive license for the Program. If IBM grants you
 multiple licenses for the Program, the terms of this Agreement apply to
 each license. The term "Program" means the original program and all
 whole or partial copies of it, including portions merged into other
 programs. A Program consists of machine-readable instructions,
 audio/visual content (such as images, text, recordings, or pictures), and
 related licensed materials.

 This Agreement includes Part 1 - General Terms and Part 2 - Country
 Unique Terms. The terms of Part 2 may replace or modify those of Part 1.
 "License Information," which IBM provides for the Program, may contain
 additional terms regarding the Program. Any such additional terms are
 part of this Agreement.
 
 1. License

 Use of the Program

 You may use the Program on only one machine at any one time, except as
 otherwise stated in this section. You agree to ensure that anyone who
 uses the Program (accessed either locally or remotely) does so only for
 your authorized use and complies with the terms of this Agreement.
 A Program is considered to be in use when it resides in memory or is
 otherwise stored on a machine. A Program stored on a network server
 solely for the purpose of being distributed to other machines is not
 considered to be in use.

 IBM specifies charges for Programs based on how much you use a Program
 (for example, the number of users), resources (for example, processor
 size), or a combination of both.

 For a Program managed by a license management tool, copies may be made
 and stored on machines under control of that tool, but your use may not
 exceed the total number of users or amount of resource authorized.
 Certain Programs IBM designates for home or travel use may be stored on
 the primary and another machine, provided the Program is not in active
 use on both machines at the same time.

 You may 1) copy the Program for backup and 2) merge the Program into
 another program. You must reproduce the copyright notice and any other
 legend of ownership on each copy, or partial copy, of the Program. You
 may use any portion of the Program IBM marks restricted (for example,
 "Restricted Materials of IBM") only to 1) resolve problems related to the
 use of the Program and 2) modify the Program so that it will work
 together with other products.

 You may not: 1) use, copy, merge, or transfer the Program except as
 provided in this Agreement; 2) reverse assemble, reverse compile, or
 otherwise translate the Program except as specifically permitted by law
 without the possibility of contractual waiver; or 3) sublicense, rent or
 lease the Program.
 
 Transfer of Rights and Obligations
 You may transfer all your rights and obligations under a license for a
 Program to another party, unless IBM specifies otherwise in its License
 Information.

 To transfer such rights and obligations, you must transfer a copy of this
 Agreement, the License Information, all other documentation (including
 proof of entitlement), and at least one complete, unaltered copy of the
 Program to the other party. Your license is then terminated.
 A Program which IBM licenses in multiples of two or more (for example, as
 a pack) may only be transferred in its entirety. In this case,
 individual licenses may not be transferred.
 
 2. Charges, Payment, and Taxes

 Payment must be made to the party (either IBM or its reseller) from whom
 you acquired the Program. If you acquired the Program from IBM, you
 agree to pay as IBM specifies. If any authority imposes a duty, tax,
 levy or fee (excluding those based on IBM's net income) on the Program
 supplied by IBM under this Agreement, you agree to pay that amount as IBM
 specifies or supply appropriate exemption documentation.
 You agree to notify IBM or its reseller and pay any applicable charges if
 you change the number of users or amount of resource authorized. IBM
 does not give refunds or credits for charges already due or paid.
 
 3. Limited Warranty

 For certain Programs IBM warrants that when they are used in the
 specified operating environment they will conform to their
 specifications. IBM does not warrant uninterrupted or error-free
 operation of a Program. The warranty period for a Program expires when
 its Program services are no longer available. IBM will specify in its
 License Information if a Program is warranted or not warranted.
 During the warranty period warranty service is provided, without charge,
 through defect-related Program services. Program services are available
 for at least one year following a Program's general availability.
 Therefore, the duration of warranty service depends on when you obtain
 your license. If a Program does not function as warranted during the
 first year after you obtain your license and IBM is unable to make it do
 so, you may return the Program to the party (either IBM or its reseller)
 from whom you acquired it and your money will be refunded. To be
 eligible, you must have acquired the Program while Program services
 (regardless of the remaining duration) were available for it.
 THESE WARRANTIES REPLACE ALL OTHER WARRANTIES OR CONDITIONS, EXPRESS OR
 IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR
 CONDITIONS OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 These warranties give you specific legal rights, and you may also have
 other rights which vary from jurisdiction to jurisdiction. Some
 jurisdictions do not allow the exclusion or limitation of implied
 warranties, so the above exclusion or limitation may not apply to you.
 In that event such warranties are limited in duration to the warranty
 period. No warranties apply after that period.

 4. Program Services

 Defect-related Program services are provided for warranted Programs and
 for selected other Programs. If your reported problem can be reproduced
 in the specified operating environment, defect correction information, a
 restriction or a bypass will be issued. Program services are provided
 only for the unmodified portion of a current release of a Program.
 Information regarding how you may obtain Program services will be
 provided by the party (either IBM or its reseller) from whom you acquired
 the Program. The duration of Program services is specified in the
 License Information.

 5. Patents and Copyrights

 If a third party claims that a Program IBM provides to you infringes that
 party's patent or copyright, IBM will, at its expense, defend you against
 that claim and pay all costs, damages, and attorney's fees that a court
 finally awards, provided that you 1) promptly notify IBM in writing of
 the claim and 2) allow IBM to control, and cooperate with IBM in, the
 defense and any related settlement negotiations. If such a claim is made
 or appears likely to be made, you agree to permit IBM to enable you to
 continue to use the Program, or to modify it, or replace it with one that
 is at least functionally equivalent. If IBM determines that none of
 these alternatives is reasonably available, you agree to return the
 Program to IBM on IBM's written request. IBM will then give you a credit
 for a one-time charge Program, provided its total charges have been fully
 paid. This is IBM's entire obligation to you regarding any claim of
 infringement. IBM has no obligation regarding any claim based on any of
 the following: 1) your modification of a Program; 2) the combination,
 operation, or use of a Program with any programs, data, or apparatus that
 IBM did not provide; or 3) infringement by a non-IBM Program.

 6. Limitation of Liability

 Regardless of the basis on which you may be entitled to recover damages
 from IBM, for any claim (including fundamental breach, negligence,
 misrepresentation or other tort), IBM's liability will only be for 1)
 payments referred to in the patents and copyrights terms described above;
 2) bodily injury (including death), and damage to real property and
 tangible personal property; and 3) the amount of any other actual direct
 damages or loss, up to the greater of the equivalent of U.S. $100,000 in
 your local currency or IBM's then generally available license charge for
 the Program.

 IBM WILL NOT BE LIABLE FOR ANY SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES
 OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR
 SAVINGS), EVEN IF IBM, OR ITS RESELLER, HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW THE
 EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE
 ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU.

 IBM will not be liable for 1) loss of, or damage to, your records or data
 or 2) any damages claimed by you based on any third party claim.
 This limitation of liability also applies to any developer of a Program
 supplied to IBM. It is the maximum for which we are collectively
 responsible.

 7. General

 You may terminate your license at any time. If you do so, all your
 license rights to the Program are terminated. You may keep a copy of the
 Program in your archives. IBM may terminate your license if you fail to
 comply with the terms of this Agreement. If IBM does so, all your
 license rights to the Program are terminated and you must destroy all
 your copies of it.
 You agree to comply with all applicable export laws and regulations.
 Neither party may bring a legal action under this Agreement more than two
 years after the cause of action arose.
 This Agreement is governed by the laws of the country in which you
 acquired the Program.
 
 -------------------------------------------------------------------------
 IBM International Program License Agreement
 Part 2 - Country Unique Terms
 -------------------------------------------------------------------------

 AUSTRALIA: Limited Warranty (Section 3): The warranties specified this
 Section are in addition to any rights you may have under the Trade
 Practices Act or other legislation and are only limited to the extent
 permitted by the applicable legislation.
 Limitation of Liability (Section 6): The following paragraph is added to
 this Section:
 Where IBM is in breach of a condition or warranty implied by the Trade
 Practices Act 1974, IBM's liability is limited to: (a) where IBM
 supplied services - the cost of having the services supplied again; or
 (b) where IBM supplied goods - the repair or replacement of the goods, or
 the supply of equivalent goods. Where that condition or warranty relates
 to right to sell, quiet possession or clear title, or the goods are of a
 kind ordinarily acquired for personal, domestic or household use or
 consumption, then none of the limitations in this paragraph apply.

 CANADA: General (Section 7): This Agreement is governed by the laws of
 the Province of Ontario.

 CENTRAL EUROPE & RUSSIA: General (Section 7): This Agreement is governed
 by the material laws of Austria. All disputes and controversies between
 the parties arising out of, or in connection with, this Agreement or its
 implementation, performance or interpretation, shall be finally settled
 under the Rules of Arbitration and Reconciliation of the Arbitral Centre
 of the Federal Economic Chamber in Vienna (Vienna Rules), by three
 arbitrators appointed in accordance with said Rules. The arbitration
 shall be held in Vienna, Austria. The official language of the
 proceedings shall be English. The decision of the arbitrators shall be
 final and binding upon both parties and therefore, the parties pursuant
 to paragraph 598(2) of the Austrian Code of Civil Procedure, expressly
 waive the application of paragraph 595(1), figure 7 of said Code. The
 clauses set forth above shall, however, in no way limit our right to
 institute proceedings in any competent court.

 ESTONIA, LATVIA, LITHUANIA: General (Section 7): All disputes arising in
 connection with the present Agreement shall be finally settled in
 Arbitration. Each party shall appoint one arbitrator and they shall
 jointly appoint the chairman. If they cannot agree on the chairman, then
 the chairman shall be appointed by the Central Chamber of Commerce in
 Helsinki. In the Arbitration the law on Arbitration will be adhered to.
 Finnish law shall apply. The arbitrators shall come together in
 Helsinki.

 GERMANY, AUSTRIA, SWITZERLAND: Limited Warranty (Section 3): The
 warranty for an IBM Program covers the functionality of the Program for
 its normal use. In case a Program is delivered without specifications,
 IBM will only warrant that the Program information correctly describes
 the Program and that the Program can be used according to the Program
 information. In case non-IBM Programs are contracted by IBM and
 delivered by IBM, the warranty for IBM Programs is applicable unless
 otherwise agreed in a transaction document. Warranty service for non-IBM
 Programs may be performed by non-IBM manufacturers.
 Limitation of Liability (Section 6): The limitations and exclusions
 specified in the Agreement will not apply to damages caused by us with
 intention or gross negligence. IBM is liable for assured
 characteristics.
 General (Section 7): The limitation on bringing a legal action is not
 applicable in case of tort by either IBM or you, or our agents.

 ISRAEL: General (Section 7): The limitation on bringing a legal action
 will be according to the law of limitation provided a notification
 concerning the cause of action was sent no more than two years after the
 cause of action arose or became known to plaintiff.

 IRELAND: Limited Warranty (Section 3): No statement in this Agreement
 shall affect the statutory rights of consumers.
 
 MIDDLE EASTERN COUNTRIES: ABU-DHABI(UAE), BAHRAIN, DUBAI(UAE), OMAN,
 KUWAIT, QATAR
 General (Section 7): This Agreement is governed by the law and
 jurisdiction of Bahrain.

 NEW ZEALAND: Limited Warranty (Section 3): The warranties specified in
 this Section are in addition to any rights you may have under the
 Consumers Guarantee Act 1993 or other legislation which cannot be
 excluded or limited. The Consumer Guarantees Act 1993 will not apply in
 respect of any goods or services which IBM provides, if you require the
 goods or services for the purposes of a business as defined in that Act.
 Limitation of Liability (Section 6): The following paragraph should be
 added to this Section:
 Where products or services are not acquired for the purposes of a
 business as defined in the Consumer Guarantees Act 1993, the limitations
 in this Section are subject to the limitations in that Act.

 PEOPLE'S REPUBLIC OF CHINA: Charges, Payment, and Taxes (Section 2): All
 banking charges incurred in the People's Republic of China shall be borne
 by you and those incurred outside the People's Republic of China shall be
 borne by us.
 General (Section 7): The laws of the State of New York govern this
 Agreement. Any dispute concerning this Agreement may be settled by
 arbitration. The arbitration will take place in Stockholm, Sweden, under
 the auspices of the International Arbitration Center in English in
 accordance with the rules then in effect under the United Nations
 Commission on International Trade Law (UNCITRAL). The arbitration award
 will be final and binding on both parties and both parties shall act
 accordingly. The arbitration fee shall be borne by the losing party.

 UNITED KINGDOM: Limitation of Liability (Section 6): Add the following
 paragraph at the end of the first paragraph:
 The limitation of liability shall not apply to any breach of IBM's
 obligations implied by Section 12 of the Sales of Goods Act 1979 or
 Section 2 of the Supply of Goods and Services Act 1982.

 UNITED STATES OF AMERICA: General (Section 7): This Agreement is
 governed by the laws of the State of New York.
 
 
 -------------------------------------------------------------------------
 Part 3 - License Information for "IBM AIX Java Diagnostic Tools"
	 	  ( fd_leak_report.sh )
 -------------------------------------------------------------------------
 
   THIS PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EX-
   PRESS   OR   IMPLIED,   INCLUDING   THE   IMPLIED   WARRANTIES   OF
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IBM does not
   warrant uninterrupted or error free operation of  the  Program,  or
   that the Program is free from claims by a third party of copyright,
   patent, trademark, trade secret, or any other intellectual property
   infringement.    IBM  has  no obligation to provide service, defect
   correction, or any maintenance for the Program. IBM  has  no  obli-
   gation to supply any Program updates or enhancements to you even if
   such are or later become available.
 
   Under no circumstances is IBM liable for any of the following:
 
   1.  third-party claims against you for losses or damages;
   2.  loss of, or damage to, your records or data; or
   3.  direct  damages,  lost  profits, lost savings, incidental, spe-
       cial, or indirect damages or other consequential damages,  even
       if IBM or its authorized supplier, has been advised of the pos-
       sibility of such damages.
 
   Some jurisdictions do not allow these limitations or exclusions, so
   they may not apply to you.
END_OF_LICENSE
	 	
	 	return 0;
}

fShowHelp() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

cat << END_OF_HELP >&2

[ USAGE ] ${sBaseName} options

Options:

-a AWK_FILTER			(optional: default is ${0}.COMMAND.filter.awk)	
	- uses the specified AWK_FILTER to display results
	- the default is ${0}.COMMAND.filter.awk where COMMAND is from -c option

-c COMMAND			(required: either -c or -f must be specified)
	- runs the COMMAND for the designated interval
	- must provide a ${0}.COMMAND.filter.awk to process (e.g., ${0}.lsof.filter.awk)
	- must be preceded by -F option when using -f option
	- not valid with -f option when not preceded by -F option

-d				(optional)		
	- enable DEBUG. Cannot be used with -q

-E				(optional)
	- runs the ${0}.extra file during each interval
	- the timer for the next interval will not start until the extra script has completed
	- use this as way to collect additional information during each interval

-f PLAYBACK_FILE		(requied: either -f or -c must be specified)
	- processes the designaed log file as a playback file through the command filter
	- must be preceed by the -F option
	- not valid with -c option when not preceded by -F option
	- the PLAYBACK_FILE can be created by using the -l option

-F				(required: must be used when both -f and -c are used)
	- indicates to use the playback file (-f) instead of the running the live command

-h				(optional)
-h -a AWK_FILTER 
	- when not used -a, shows this help
	- when used with -a, will display the help from the AWK filter

-i "INTERVAL_TIME #_INTERVALS" 	(optional: default is unlimited 60 second intervals)
-i "INTERVAL_TIM"		
	- designate the time (in seconds) between intervals (INTERVAL_TIME) and the number of intervals (#_INTERVALS)
	- when #_INTERVALS is not specified, run until killed or until STOPFILE (see -S) is created
	- when specifying both values, enclose in quotes
	- default value is 60 seconds

-I				(optional)
	- when using -r t (report time), show the time between intervals, not the actual timestamp

-l LOGFILE			(optional)
	- only value with -c option
	- not value with -f option
	- appends the output of the command executed in the designated file
	- must include the -O option to overwrite the file if it already exists

-L a				(required)
-L s
	- use "s" to view current license details
	- use "a" to accept license and run tool

-M MIN_THRESHOLD		(not implemented)
	- will be filter specific

-n "NAME1|NAME2|NAME"		(optional)
	- a "|" delimited list of names to filter the results
	- how the names are filtered are specific to the command filter (see -a)

-o OUTPUT_FILE			(optional: default is to the screen/terminal)
	- writes output to the designated file instead of the terminal/window
	- must be proceeded with -O to overwrite an existing file

-O				(optional)
	- indicates that all output files (e.g., -l, -o) can be overwritten

-p "PID|PID|PID"		(optional)
	- a "|" delinmited list of process ids to filter the results
	- how and if the pids are filtered are specific to the command filter (see -a)

-P PERCENT_THRESHOLD		(not implemented)
	- will be filter specific

-q				(optional)	
	- surpress information messages
	- can not be used with -d option

-r b	(report basic)			(optional: default is -r b)
-r d	(report details)
-r f	(report flags)
-r t	(report time)
-r T	(report trend)
-r TA	(report trend)
	- "b"		display basic summary
	- "d"		display detail summary
	- "r"		display flags or indicators
	- "t"		display timestamps, intervals, 
	- "T" or "TA"	display trend information
	- one or more combinations of -r # flags can be used:
		-r b -r d -r f -r t ...
	- the output will be specific to the filter

-S STOP_FILE				(optional: default is ${0}.stop)
	- indicates to stop the script once this file is created
	- the file can not exist prior to starting the process
	- the default is ${0}.stop

-t "TYPE|TYPE|TYPE"			(optional)
	- a "|" delinmited list of types to filter the results
	- how and if the types are filtered are specific to the command filter (see -a)

-u "USERID|USERID|USERID"		(optional)
	- a "|" delinmited list of userids to filter the results
	- how and if the users are filtered are specific to the command filter (see -a)

Examples:

{must have showstat.sh.lsof.filter.awk located in the same directory}
# showstat.sh -c lsof -l lsof_output.txt -i "2" -r b -r d -r t
# showstat.sh -c lsof -l lsof_output.txt -p "123412|1251232" -i "2" -r b -r d -r t
# showstat.sh -c lsof -l lsof_output.txt -n "java|sshd" -i "2" -r b -r d -r t
# showstat.sh -c lsof -l lsof_output.txt -t "vreg|unix|ipv" -i "2" -r b -r d -r t

{must have showstat.sh.lsof.filter.awk located in the same directory}
{lsof_output.txt must exit}
# showstat.sh -F -f lsof_output.txt -c lsof -i "2" -r b -r d -r t
# showstat.sh -F -f lsof_output.txt -c lsof -u "root|wasusr|oracle|db" -i "2" -r b -r d -r t
# showstat.sh -F -f lsof_output.txt -c lsof -t "s" -i "2" -r b -r d -r t
# showstat.sh -F -f lsof_output.txt -c lsof -t "m" -i "2" -r b -r d -r t

{must have showstat.sh.ipcs_cmd.filter.awk located in the same directory}
# showstat.sh -l ipcs_output.txt  -c ipcs_cmd -i "2 10" -r b -r d -r t


END_OF_HELP

	 	return 0;
}

fPrefixMsg() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

	 	_sDate="$( date +"%C%y.%02m.%02d.%02H.%02M.%02S.%s" )"
	 	sed -e "s|^|[ ${sBaseName} ] [ ${_sDate} ] |g"

	 	return 0;
}

fPrintMsg() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

	 	if (( ${bQuietMode:-0} == 0 )); then
	 		 	echo "${*}" | fPrefixMsg >&2
	 	fi

	 	return 0;
}

fCleanup() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

	 	fPrintMsg "[ INFO ] Exit reason= ${2:-STOPPED_BY_SCRIPT}" 
	 	
	 	if [ -n "${aTmpFile[*]}" ]; then
	 		 	rm -f ${aTmpFile[*]} >/dev/null 2>&1
	 	fi

	 	exit "${1}"

	 	return 0;
}

fRunReport() {
	 	if (( ${bDebugMode:-0} == 1 )); then set -x; fi

	 	{
	 	if [ -n "${sMONITORfile}" ]; then
	 		 	${sDataCmd}
	 	else

	 	(( iIntervalCt	 	= 1 ))

	 	while (( ${iIntervalMax:-0} == 0 )) || (( iIntervalCt <= ${iIntervalMax:-0} )); do

	 		 	fPrintMsg "[ INFO ] interval delay= ${iIntervalDelay:-${iIntervalDelay:-30}} max_count= ${iIntervalMax:-0} cur_count= ${iIntervalCt}"

				export sDATEstr="## DATE: $( date +"%C%y.%02m.%02d.%02H.%02M.%02S.%s")"
				export sLOGfile iIntervalCt

				_sWaitfor=""
				if (( bRunEXTRAfile == 1 )) && [ -n "${sEXTRAfile}" ] && [ -n "${sLOGfile}" ]; then
					"${sEXTRAfile}" &
					_sWaitfor="${!}"
				fi

	 		 	${sDataCmd} |\
	 		 	{
	 		 	 	if [ -n "${sLOGfile}" ]; then
	 		 		 	{
							echo "${sDATEstr}"
	 		 	  		 	cat
							echo "${sDATEstr}"
	 		 	 		 	echo 
	 		 	 	 	} | tee -a "${sLOGfile}"
	 		 	 	else
						echo "${sDATEstr}"
	 		 		 	cat
						echo "${sDATEstr}"
	 		 		 	echo
	 		 	 	fi
	 		 	} 
				if [ -n "${_sWaitfor}" ]; then
					wait "${_sWaitfor}"
				fi

	 		 	sleep ${iIntervalDelay:-${iIntervalDelay:-30}}
	 		 	(( iIntervalCt	 	= iIntervalCt + 1 ))
	 	done

	 	fi
	 	} | ${sReportCmd}

	 	return 0;
}

# -f ${sDEFAULTcmd}_output | -c full_path_${sDEFAULTcmd}	 		 	[ default is -c $(which ${sDEFAULTcmd}) ]
# -L s [show] | -L a [accept]	 		 		 	[ -L a required to run ]	 	
# -i "interval" | -i "interval count"	 		 	[ if -c then default is "0 1", if ignored ]
# -p "all" | -p "pid|pid|pid"	 		 		 	[ default is  -p "all" ]
# -t "all" | -t "fifo|file|dir|unix|ipv"	 	[ default is -t "all" ]
# -n "all" | -n "name|name|name"	 		 	[ default is -n "all" ]
# -u "all" | -u "name|name|name"	 		 	[ default is -u "all" ]
# -l log	 		 		 		 		 	[ ${sDEFAULTcmd} log file
# -r b [basic] | -r d [detail] | -r f [flags] -r t [time] -r T [trend] -r TA [trend all] 	 		 		 	[ default is -r b ]
# -q	 		 		 		 		 		 	[ default is show all messages ]
# -d	 		 		 		 		 		 	[ default is not to show debug ]
# -O	 		 		 		 		 		 	[ default is not to overwrite files ]
# -o output	 		 		 		 		 	[ output file ]
# -a awk_filter	 		 		 		 		 	[ default is $0.awk ]
# -I							[ default is to show time if available ]

typeset -i iPERCENTthreshold=50
typeset -i iMINthreshold=2000

while getopts "IEa:f:c:FL:i:p:t:n:r:qdOo:l:hP:M:u:S:" opt; do

	 	case "${opt:-h}" in

		"S" )	if [ -z "${OPTARG}" ]; then
	 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} is not accessible." >&2
	 		 	fCleanup 1 COMMAND_LINE_ERROR
			elif [ -f "${OPTARG}" ]; then
	 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} already exists and must be removed." >&2
	 		 	fCleanup 1 COMMAND_LINE_ERROR
			elif ! touch "${OPTARG}" >/dev/null 2>&1; then
	 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} can not be created. Check permissions." >&2
	 		 	fCleanup 1 COMMAND_LINE_ERROR
			fi
			rm -f "${OPTARG}"
			sSTOPfile="${OPTARG}"
			;;

		"I" )	(( bShowInterval = 1 ))
			;;

		"E")	(( bRunEXTRAfile	= 1 ))
			if [ -z "${sEXTRAfile}" ]; then
				echo "[ ERROR ] There is no file= ${0}.extra to run." >&2
				fCleanup 1 COMMAND_LINE_ERROR
			fi
			;;

		"F" )	(( bUSEfile = 1 ))
			;;

	 	"a" )
	 		 	sAWKfilter="${OPTARG:-${0}.awk}"
	 		 	if [ ! -f "${sAWKfilter}" ]; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} is not accessible." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
				(( bShowFilterHelp = 1 ));			
	 	 	 	 ;;

	 	"M" )
	 		 	iMINthreshold=${OPTARG:-${iMINthreshold}}
	 		 	if (( ${?} != 0 )); then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_VALUE_SPECIFIED} is not a valid value for the -M parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	;;

	 	"P" )
	 		 	iPERCENTthreshold=${OPTARG:-${iPERCENTthreshold}}
	 		 	if (( ${?} != 0 )); then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_VALUE_SPECIFIED} is not a valid value for the -P parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	;;

	 	"l" )
	 		 	if [ -n "${sMONITORfile}" ]; then
	 		 		 	echo "[ ERROR ] -f and -l parameters cannot be used at the same time." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_NAME_SPECIFIED} is not a valid value for the -l parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ -f "${OPTARG}" ] && (( bDoOverwriteFiles == 0 )); then
	 		 		 	echo "[ ERROR ] The file=  ${OPTARG:-NO_FILE_SPECIFIED} exists.  Use -O parameter before -l to overwrite." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif ! echo "" > "${OPTARG}" >/dev/null 2>&1; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} cannot be created or updated." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	sLOGfile="${OPTARG}"
	 		 	;;

	 	"n" )
	 		 	if [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_NAME_SPECIFIED} is not a valid value for the -n parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	else
	 		 		 	sNAMEpattern="$( echo "${OPTARG}" | sed -e "s|[Aa][Ll][Ll]|\.|g" )"
	 		 	fi
	 		 	;;

	 	"u" )
	 		 	if [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_NAME_SPECIFIED} is not a valid value for the -u parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	else
	 		 		 	sUSERpattern="$( echo "${OPTARG}" | sed -e "s|[Aa][Ll][Ll]|\.|g" )"
	 		 	fi
	 		 	;;

	 	"p" )
	 		 	if [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_PID_SPECIFIED} is not a valid value for the -p parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	else
	 		 		 	sPIDpattern="$( echo "${OPTARG}" | sed -e "s|[Aa][Ll][Ll]|\.|g" )"
	 		 	fi
	 		 	;;

	 	"t" )
	 		 	if [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The value= ${OPTARG:-NO_TYPE_SPECIFIED} is not a valid value for the -t parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	else
	 		 		 	sTYPEpattern="$( echo "${OPTARG}" | sed -e "s|[Aa][Ll][Ll]|\.|g" )"
	 		 	fi
	 		 	;;

	 	"O" )
	 		 	(( bDoOverwriteFiles = 1 ))
	 		 	;;

	 	"o" )
	 		 	if [ -z "${OPTARG}" ]; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} is not a valid value for the -o parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ -f "${OPTARG}" ] && (( bDoOverwriteFiles == 0 )); then
	 		 		 	echo "[ ERROR ] The file=  ${OPTARG:-NO_FILE_SPECIFIED} exists.  Use -O parameter before -o to overwrite." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif ! echo "" > "${OPTARG}" >/dev/null 2>&1; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} cannot be created or updated." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	sREPORTfile="${OPTARG}"
	 		 	;;

	 	"q" )
	 		 	if (( ${bDebugMode:-0} == 1 )); then
	 		 		 	echo "[ ERROR ] -d and -q parameters cannot be used at the same time." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	(( bQuietMode	 	= 1 ))
	 		 	;;


	 	"d" )
	 		 	if (( ${bQuietMode:-0} == 1 )); then
	 		 		 	echo "[ ERROR ] -d and -q parameters cannot be used at the same time." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	(( bDebugMode	 	= 1 ))
	 		 	set -x
	 		 	;;

	 	"f" )
	 		 	if [ -n "${sLOGfile}" ]; then
	 		 		 	echo "[ ERROR ] -f and -l parameters cannot be used at the same time." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif (( ${iIntervalDelay:-0} + ${iIntervalMax:-0} > 0 )); then
	 		 		 	echo "[ ERROR ] -f and -i parameters cannot be used at the same time." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ -n "${sMONITORcmd}" ] && (( bUSEfile == 0 )); then
	 		 		 	echo "[ ERROR ] -f and -c parameters cannot be used at the same time without -F." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ ! -f "${OPTARG:-NO_FILE_SPECIFIED}" ]; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} is not accessible." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	sMONITORfile="${OPTARG}"
	 		 	;;

	 	"c" )
	 		 	_tmp="$( which ${OPTARG:-NO_FILE_SPECIFIED} )"
	 		 	if [ -f "${_tmp}" ]; then
	 		 		 	OPTARG="${_tmp}"
	 		 	fi
	 		 	if [ -n "${sMONITORfile}" ] && (( bUSEfile == 0 )); then
	 		 		 	echo "[ ERROR ] -f and -c parameters cannot be used at the same time without -F." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	elif [ ! -f "${OPTARG:-NO_FILE_SPECIFIED}" ]; then
	 		 		 	echo "[ ERROR ] The file= ${OPTARG:-NO_FILE_SPECIFIED} is not accessible." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	sMONITORcmd="${OPTARG}"
	 		 	;;

	 	"L" )
	 		 	if [ x"${OPTARG}"x = x"s"x ]; then
	 		 		 	fShowLicense
	 		 		 	fCleanup 0
	 		 	elif [ x"${OPTARG:-NO_VALUE_SPECIFIED}"x != x"a"x ]; then
	 		 		 	echo "[ ERROR ] Invalid value '${OPTARG:-NO_VALUE_SPECIFIED}' for -L parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	fi
	 		 	(( bAcceptedLicense = 1 ))
	 		 	;;

	 	"i" )
#	 		 	if [ -n "${sMONITORfile}" ]; then
#	 		 		 	echo "[ ERROR ] -f and -i parameters cannot be used at the same time." >&2
#	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
#	 		 	fi
	 	
	 		 	i1="${OPTARG%% *}"
	 		 	i2="${OPTARG##* }"

	 		 	if [ -n "${i1}" ] && [ x"${i1}"x = x"${i2}"x ]; then
	 		 		 	iIntervalDelay=${i1}
	 		 		 	if (( ${?} != 0 )); then
	 		 		 		 	echo "[ ERROR ] The value '${i1}' does not appear to be a valid number with the -i parameter." >&2
	 		 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 		 	fi
	 		 	elif [ -n "${i1}" ]; then
	 		 		 	iIntervalDelay=${i1}
	 		 		 	if (( ${?} != 0 )); then
	 		 		 		 	echo "[ ERROR ] The value '${i1}' does not appear to be a valid number with the -i parameter." >&2
	 		 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 		 	fi
	 		 		 	iIntervalMax=${i2}
	 		 		 	if (( ${?} != 0 )); then
	 		 		 		 	echo "[ ERROR ] The value '${i2}' does not appear to be a valid number with the -i parameter." >&2
	 		 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 		 	fi
	 		 	fi
	 		 	;;

	 	"r" )
	 		 	if [ x"${OPTARG}"x = x"d"x ]; then
	 		 		 	(( bReportDetails	 	= 1 ))
	 		 	elif [ x"${OPTARG}"x = x"f"x ]; then
	 		 		 	(( bReportFlags	 	= 1 ))
	 		 	elif [ x"${OPTARG}"x = x"T"x ]; then
	 		 		 	(( bReportTrend	 	= 1 ))
	 		 	elif [ x"${OPTARG}"x = x"TA"x ]; then
	 		 		 	(( bReportTrend	 		 	= 1 ))
	 		 		 	(( bReportTrendAll	 	= 1 ))
	 		 	elif [ x"${OPTARG}"x = x"t"x ]; then
	 		 		 	(( bReportTime	 	= 1 ))
	 		 	elif [ x"${OPTARG:-NO_VALUE_SPECIFIED}"x != x"b"x ]; then
	 		 		 	echo "[ ERROR ] Invalid value '${OPTARG:-NO_VALUE_SPECIFIED}' for -r parameter." >&2
	 		 		 	fCleanup 1 COMMAND_LINE_ERROR
	 		 	else
	 		 		 	(( bReportBasic	 	= 1 ))
	 		 	fi
	 		 	;;

	 	"h" | * ) 
				(( bShowHelp = 1 ))
	 		 	;;


	 	esac

done

if [ -f "${sSTOPfile}" ]; then
	echo "[ ERROR ] The file= ${sSTOPfile} already exists and must be removed." >&2
	fCleanup 1 
fi

if [ -z "${sPIDpattern}" ]; then
	 	sPIDpattern="."
else
	 	#sPIDpattern="$( echo "${sPIDpattern}" | sed -e "s|^| |g" -e "s|$| |g" -e "s/|/ | /g" )"
	 	:
fi
if [ -z "${sNAMEpattern}" ]; then
	 	sNAMEpattern="."
else
	 	#sNAMEpattern="$( echo "${sNAMEpattern}" | sed -e "s|^|^|g" -e "s|$| |g" -e "s/|/ | /g" )"
	 	:
fi
if [ -z "${sUSERpattern}" ]; then
	 	sUSERpattern="."
else
	 	#sUSERpattern="$( echo "${sUSERpattern}" | sed -e "s|^|^|g" -e "s|$| |g" -e "s/|/ | /g" )"
	 	:
fi
if [ -z "${sTYPEpattern}" ]; then
	 	sTYPEpattern="."
else
	 	#sTYPEpattern="$( echo "${sTYPEpattern}" | sed -e "s|^| |g" -e "s|$| |g" -e "s/|/ | /g" )"
	 	:
fi

if [ -z "${sMONITORfile}" ] && [ -z "${sMONITORcmd}" ]; then
	 	sMONITORcmd="$( which ${sDEFAULTcmd} 2>&1 )"
	 	if [ -z "${sMONITORcmd}" ] || [ ! -f "${sMONITORcmd}" ]; then
	 		 	echo "[ ERROR ] The file= ${sMONITORcmd:-NO_FILE_SPECIFIED} is not accessible." >&2
	 		 	fCleanup 1
	 	fi
fi

if [ -n "${sMONITORcmd}" ] && (( bUSEfile == 0 )); then
	 	sDataCmd="${sMONITORcmd}"
	 	if (( ${iIntervalDelay:-0} == 0 )); then
	 		 	(( iIntervalDelay = iDefaultDelay ))
	 	fi
else
	 	sDataCmd="cat ${sMONITORfile}"
#	 	(( iIntervalDelay = 0 ))
	 	(( iIntervalMax = 1 ))
fi

if (( ( bReportBasic + bReportDetails + bReportTrend + bReportTime + bReportTrendAll) ==  0 )); then
	 	(( bReportBasic	 	= 1 ))
fi

if [ -z "${sMONITORfile}" ]; then
	 	(( bSkipTime	 	= 0 ))
else
	 	(( bSkipTime	 	= 1 ))
fi

if [ -z "${sAWKfilter}" ]; then
	 _sTmpCmd="${sMONITORcmd##*/}"
	 if [ -f "${sBaseDir}/${_sTmpCmd:-${sDEFAULTcmd}}.filter.awk" ]; then
	 	 sAWKfilter="${sBaseDir}/${_sTmpCmd:-${sDEFAULTcmd}}.filter.awk"
	 elif [ -f "${0}.${_sTmpCmd:-${sDEFAULTcmd}}.filter.awk" ]; then
	 	 sAWKfilter="${0}.${_sTmpCmd:-${sDEFAULTcmd}}.filter.awk"
	 else
	 	 sAWKfilter="${0}.filter.awk"
	 fi
fi

if [ ! -f "${sAWKfilter}" ]; then
	 	echo "[ ERROR ] The file= ${sAWKfilter:-NO_FILE_SPECIFIED} is not accessible." >&2
	 	fCleanup 1 
fi

if (( bShowHelp == 1 )); then
	if (( bShowFilterHelp == 1 )); then
		echo | awk -f "${sAWKfilter}" bShowHelp=1
	else
		fShowHelp
	fi
	fCleanup 0
fi

fGetTmpFile	 	# make sure we can get a tmp file before continuing
_id="${?}"

sReportCmd="awk -f ${sAWKfilter} bBasic=${bReportBasic} iPERCENTthreshold=${iPERCENTthreshold} iMINthreshold=${iMINthreshold} sPIDpattern=${sPIDpattern} sNAMEpattern=${sNAMEpattern} sUSERpattern=${sUSERpattern} sTYPEpattern=${sTYPEpattern} bSkipTime=${bSkipTime} iIntervalDelay=${iIntervalDelay} bReportBasic=${bReportBasic} bReportDetails=${bReportDetails} bReportTrend=${bReportTrend} bReportTrendAll=${bReportTrendAll} bReportTime=${bReportTime} bReportFlags=${bReportFlags} bShowInterval=${bShowInterval}"

if (( ${bQuietMode:-0} == 0 )); then
cat << END_OF_CAT | sed -e "s|^|[ INFO ] |g" | fPrefixMsg >&2

Parameters:
-c ${sMONITORcmd:-NOT_SET} | -f ${sMONITORfile:-NOT_SET}
-r b=${bReportBasic} | -r f=${bReportDetails} | -r t=${bReportTime} | -r T=${bReportTrend} | -r TA=${bReportTrendAll}  | -r f=${bReportFlags}
-i "${iIntervalDelay} ${iIntervalMax}"
-p ${sPIDpattern:-all}
-t ${sTYPEpattern:-all}
-n ${sNAMEpattern:-all}
-u ${sUSERpattern:-all}
-o ${sREPORTfile:-NO_SET}
-l ${sLOGfile:-NO_SET}
-d=${bDebugMode}
-q=${bQuietMode}
-L a=${bAcceptedLicense}
-M ${iMINthreshold}
-P ${iPERCENTthreshold}
-O ${bDoOverwriteFiles}
-S ${sSTOPfile}
-a ${sAWKfilter}
-I ${bShowInterval}

Values:
sDataCmd=${sDataCmd}
sReportCmd=${sReportCmd}

END_OF_CAT
fi

if (( bAcceptedLicense == 0 )); then
	 	echo "[ ERROR ] License must be accepted to use this script." >&2
	 	fCleanup 1 LICENSE_ERROR
fi

if [ -n "${sREPORTfile}" ]; then
	 	exec >> "${sREPORTfile}"
fi

fRunReport 

fCleanup 0


