#!/bin/bash

SVER='3.2.11-1'
SDATE='2025 Jun 30'

##############################################################################
#  supportconfig - Gathers system troubleshooting information for SUSE Support
#  Copyright (C) 2001-2025 SUSE LLC
#
#  Creates a tar ball to attach to the support case or send to support. 
#  Collects comprehensive system information for troubleshooting and reducing
#  resolution time.
#
#  Disclaimer:
#  Detailed system information and logs are collected and organized in a
#  manner that helps reduce service request resolution times. Private system
#  information can be disclosed when using this tool. If this is a concern,
#  please prune private data from the log files. Several startup options 
#  are available to exclude more sensitive information. Use supportconfig -h 
#  to see these options.
##############################################################################
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; version 2 of the License.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, see <http://www.gnu.org/licenses/>.
#
#  Authors/Contributors:
#     Jason Record <jason.record@suse.com>
#
##############################################################################

##############################################################################
# SUSE Function Definitions
##############################################################################

title() {
	echo "============================================================================="
	echo "                     Support Utilities - Supportconfig"
	echo "                          Script Version: $SVER"
	echo "                         Library Version: $RCVER"
	echo "                          Script Date: $SDATE"
	echo 
	echo " Detailed system information and logs are collected and organized in a"
	echo " manner that helps reduce service request resolution times. Private system"
	echo " information can be disclosed when using this tool. If this is a concern,"
	echo " please prune private data from the log files. Several startup options"
	echo " are available to exclude more sensitive information. Supportconfig data is"
	echo " used only for diagnostic purposes and is considered confidential information."
	echo " See http://www.suse.com/company/policies/privacy/"
	echo "============================================================================="
	echo
}

show_help() {
	log2sys "Show Help Screen"
	echo " Usage: $CURRENT_SCRIPT [OPTION [OPTION ...]]"
	echo
	echo "  -h This screen"
	echo "  -A Activates all supportconfig functions with additional logging and full"
	echo "     rpm verification."
	echo "  -B <string> Custom tar ball file name element"
	echo "  -C Creates a new default $SC_CONF"
	echo "  -D Use defaults; ignore  $SC_CONF"
	echo "  -E <string> Contact email address"
	echo "  -F Display available supportconfig feature keywords (case-sensitive) used"
	echo "     with -i and -x"
	echo "  -G <gpg_uid> The GPG recipient's user ID used to encrypt the supportconfig tarball"
	echo "  -H <number> Limit number of included HA Policy engine files"
	echo "  -I <number> Default log file line count"
	echo "  -J Collect memory information from sysfs"
	echo "  -L Create a full file listing from '/'"
	echo "  -M <string> Contact terminal ID"
	echo "  -N <string> Contact name"
	echo "  -O <string> Contact company name"
	echo "  -P <string> Contact phone number"
	echo "  -Q Run in silent mode"
	echo "  -R <path> Log output directory"
	echo "  -S <number> Limit number of included SAR files"
	echo "  -T <seconds> Binary execution timeout"
	echo "  -U <URI string> Sets upload target URL and initiates an upload, supported"
	echo "                  services include: ftp, ftps/ftpes, https, scp"
	echo "  -V <key:value> Include a key/value pair in summary.xml under the <customer> tag. This option is repeatable."
	echo "  -X <number> Max system logs line count"
	echo "  -a Upload the tar ball to the specified alternate target VAR_OPTION_UPLOAD_TARGET_ALT"
	echo "  -b Screen buffer mode"
	echo "  -c Disables curl checks to SUSE update servers"
	echo "  -d Exclude detailed disk info and scans"
	echo "  -e Disables extended scaling, forcing the gathering of extended proc and irq data"
	echo "  -f From directory. Don't collect report files, just use the directory or files in that"
	echo "     directory."
	echo "  -g Use gzip instead of the default xz compression"
	echo "  -i <keyword list>"
	echo "     Include keywords. A comma separated list of feature keywords that specify"
	echo "     which features to include. Use -F to see a list of valid keywords."
	echo "  -k disable all commands that do automatic kernel module loading."
	echo "  -l Gathers additional rotated logs"
	echo "  -m Only gather a minimum amount of info: basic env, basic health, hardware,"
	echo "     rpm, messages, y2logs"
	echo "  -o Toggle listed features on or off"
	echo "  -p Disable all plugins"
	echo "  -q Add a uuid to the tar ball filename to ensure uniqueness"
	echo "  -r <srnum>"
	echo "     Includes the service request number when uploading the tar ball"
	echo "  -s Include full SLP service lists"
	echo "  -t <directory>"
	echo "     Target directory. Just save log files to <directory>, do not create a tarball."
	echo "  -u Upload the tar ball to the specified VAR_OPTION_UPLOAD_TARGET."
	echo "  -v Performs an rpm -V for each installed rpm  NOTE: This takes a long time"
	echo "     to complete"
	echo "  -w Enable verbose wait trace logging. Shows the start and stop times of each"
	echo "     command supportconfig is running."
	echo "  -x <keyword list>"
	echo "     Exclude keywords. A comma separated list of feature keywords that specify"
	echo "     which features to exclude. Use -F to see a list of valid keywords."
	echo "  -y Gathers full YaST log files."
	echo "  -z Use bzip2 instead of the default xz compression"
	echo 
	echo "  Use Ctrl-\ to try and skip a function that is hanging."
	echo
	echo "-----------------------------------------------------------------------------"
	echo "  NOTE:"
	echo "  This tool will create a tar ball in the /var/log directory. Please attach"
	echo "  the log file tar ball to your open Service Request at the following URL:"
	echo "  https://scc.suse.com/support/requests"
	echo 
	echo "  If you cannot attach the tar ball to the SR, then email it to the engineer."
	echo
	echo "  Please submit bug fixes or comments via:"
	echo "  https://en.opensuse.org/openSUSE:Submitting_bug_reports"
	echo
	title
}

basic_environment() {
	# This is a minimum required function, do not exclude
	printlog "Basic Environment..."
	(( $MIN_OPTION_ENV )) || { echolog EXCLUDED; return 1; }
	addHeaderFile $BASIC_ENVF
	get_customer_info $BASIC_ENVF
	log_cmd $BASIC_ENVF 'date'
	log_cmd $BASIC_ENVF 'uname -a'
	RELEASE=$(ls -1 /etc/*release*)
	detectProducts $BASIC_ENVF
	detectVirtualization $BASIC_ENVF
	conf_files $BASIC_ENVF $RELEASE
	log_cmd $BASIC_ENVF 'rpm -qf /etc/products.d/baseproduct'
	if ! ((NSA_CHECK)); then
		cat $LOG/$RPM_DIST_FILE >> $LOG/$BASIC_ENVF
		case $SLES_VER in
		15*|16*|999)
			if rpm_verify $BASIC_ENVF firewalld
			then
				wait_trace_on "systemctl status firewalld.service"
				log_cmd $BASIC_ENVF 'systemctl status firewalld.service'
				wait_trace_off
				IPBIN="/usr/sbin/iptables"
				if [[ -x $IPBIN ]]; then
					TOTAL_FIREWALL_RULES=0
					for TABLE in filter nat mangle raw security
					do
						if grep iptable_$TABLE /proc/modules &>/dev/null
						then
							wait_trace_on "$IPBIN -t $TABLE -nL | sed -e '/^$/d' -e '/^Chain/d' -e '/^target/d' | wc -l"
							FIREWALL_RULES=$($IPBIN -t $TABLE -nL | sed -e '/^$/d' -e '/^Chain/d' -e '/^target/d' | wc -l)
							TOTAL_FIREWALL_RULES=$(( TOTAL_FIREWALL_RULES + FIREWALL_RULES ))
							wait_trace_off
						fi
					done
					log_write $BASIC_ENVF
					log_write $BASIC_ENVF "$TOTAL_FIREWALL_RULES Active Firewall Rules"
					log_write $BASIC_ENVF
				fi
			fi
			;;
		esac
	fi
	echolog Done
}

basic_healthcheck() {
	# This is a minimum required function, do not exclude
	printlog "Basic Server Health Check..."
	(( $MIN_OPTION_HC )) || { echolog EXCLUDED; return 1; }
	OF=basic-health-check.txt
	addHeaderFile $OF
	log_cmd $OF 'uptime'
	log_cmd $OF 'grep -H . /sys/devices/system/cpu/vulnerabilities/*'
	log_cmd $OF 'vmstat 1 4'
	[[ -x /usr/bin/mpstat ]] && log_cmd $OF 'mpstat -P ALL 1 3'
	log_cmd $OF 'free -k'
	timed_log_cmd $OF 'df -h' || IO_DELAYS=1
	(( $IO_DELAYS )) || log_cmd $OF 'df -i'
	TAINT_SRC='/proc/sys/kernel/tainted'
	conf_files $OF $TAINT_SRC
	TAINT=$(cat $TAINT_SRC)
	if (( $TAINT )); then
		# TAINT=$(( 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 ))
		# Refer to /usr/src/linux/include/linux/kernel.h and /usr/src/linux/kernel/panic.c (print_tainted function)
		TAINT_STRING=""

		# common to all versions
		((TAINT & 1)) 		&& TAINT_STRING="${TAINT_STRING}P" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 2)) 		&& TAINT_STRING="${TAINT_STRING}F" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 4)) 		&& TAINT_STRING="${TAINT_STRING}S" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 8)) 		&& TAINT_STRING="${TAINT_STRING}R" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 16)) 		&& TAINT_STRING="${TAINT_STRING}M" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 32)) 		&& TAINT_STRING="${TAINT_STRING}B" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 64)) 		&& TAINT_STRING="${TAINT_STRING}U" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 128)) 	&& TAINT_STRING="${TAINT_STRING}D" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 256))		&& TAINT_STRING="${TAINT_STRING}A" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 512))		&& TAINT_STRING="${TAINT_STRING}W" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 1024))	&& TAINT_STRING="${TAINT_STRING}C" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 2048))	&& TAINT_STRING="${TAINT_STRING}I" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 4096))	&& TAINT_STRING="${TAINT_STRING}O" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 8192))	&& TAINT_STRING="${TAINT_STRING}E" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 16384))	&& TAINT_STRING="${TAINT_STRING}L" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 32768))	&& TAINT_STRING="${TAINT_STRING}K" || TAINT_STRING="${TAINT_STRING} "

		case $SLES_VER in
		150|151)
		((TAINT & 65536))      	&& TAINT_STRING="${TAINT_STRING}H" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 1073741824))	&& TAINT_STRING="${TAINT_STRING}N" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 2147483648))	&& TAINT_STRING="${TAINT_STRING}X" || TAINT_STRING="${TAINT_STRING} "
		;;
		15*|16*|999)
		((TAINT & 65536)) 		&& TAINT_STRING="${TAINT_STRING}X" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 131072)) 		&& TAINT_STRING="${TAINT_STRING}T" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 262144)) 		&& TAINT_STRING="${TAINT_STRING}H" || TAINT_STRING="${TAINT_STRING} "
		((TAINT & 2147483648))	&& TAINT_STRING="${TAINT_STRING}N" || TAINT_STRING="${TAINT_STRING} "
		;;
		esac
		log_write $OF "Kernel Status -- Tainted: $TAINT_STRING"

		# common to all versions
		((TAINT & 1)) 		&& log_write $OF "  TAINT: (P) Proprietary module has been loaded"
		((TAINT & 2)) 		&& log_write $OF "  TAINT: (F) Module was forcibly loaded"
		((TAINT & 4)) 		&& log_write $OF "  TAINT: (S) SMP with CPUs not designed for SMP"
		((TAINT & 8)) 		&& log_write $OF "  TAINT: (R) Module was forcibly unloaded"
		((TAINT & 16)) 		&& log_write $OF "  TAINT: (M) Machine check exception"
		((TAINT & 32)) 		&& log_write $OF "  TAINT: (B) System has hit bad_page"
		((TAINT & 64)) 		&& log_write $OF "  TAINT: (U) Userspace-defined problems"
		((TAINT & 128)) 	&& log_write $OF "  TAINT: (D) Kernel has oopsed before"
		((TAINT & 256)) 	&& log_write $OF "  TAINT: (A) ACPI table overridden"
		((TAINT & 512)) 	&& log_write $OF "  TAINT: (W) Taint on warning"
		((TAINT & 1024)) 	&& log_write $OF "  TAINT: (C) Modules from drivers/staging are loaded"
		((TAINT & 2048)) 	&& log_write $OF "  TAINT: (I) Working around severe firmware bug"
		((TAINT & 4096)) 	&& log_write $OF "  TAINT: (O) Out-of-tree module has been loaded"
		((TAINT & 8192)) 	&& log_write $OF "  TAINT: (E) Unsigned module has been loaded"
		((TAINT & 16384)) 	&& log_write $OF "  TAINT: (L) A soft lockup has previously occurred"
		((TAINT & 32768)) 	&& log_write $OF "  TAINT: (K) Kernel has been live patched"

		case $SLES_VER in
		150|151)
		((TAINT & 65536))      && log_write $OF "  TAINT: (H) System restored from unsafe hibernate snapshot image"
		((TAINT & 1073741824)) && log_write $OF "  TAINT: (N) Unsupported modules loaded"
		((TAINT & 2147483648)) && log_write $OF "  TAINT: (X) Modules with external support loaded"
		;;
		15*|16*|999)
		((TAINT & 65536)) 		&& log_write $OF "  TAINT: (X) Modules with external support loaded"
		((TAINT & 131072)) 		&& log_write $OF "  TAINT: (T) Kernel built with randstruct plugin"
		((TAINT & 262144)) 		&& log_write $OF "  TAINT: (H) System restored from unsafe hibernate snapshot image"
		((TAINT & 2147483648)) 	&& log_write $OF "  TAINT: (N) Unsupported modules loaded"
		;;
		esac

		log_write $OF
		LIST_MODULES_ANY=0
		for MODULE in $(cat /proc/modules | awk '{print $1}')
		do
			LIST_MODULE=0
			modinfo -l $MODULE &>/dev/null
			MOD_ERR=$?
			if (( MOD_ERR )); then
				log_write $OF "$(printf "%-25s %-25s %-25s" module=$MODULE ERROR "Module info unavailable")"
			else
				wait_trace_on "modinfo -l $MODULE"
				LIC=$(modinfo -l $MODULE | head -1)
				SUP=$(modinfo -F supported $MODULE | head -1)
				[[ -z $LIC ]] && LIC=None
				[[ -z $SUP ]] && SUP=no
				GPLTEST=$(echo $LIC | grep GPL)
				[[ -z $GPLTEST ]] && ((LIST_MODULE++))
				[[ "$SUP" != "yes" ]] && ((LIST_MODULE++))
				(( LIST_MODULE > 0 )) && log_write $OF "$(printf "%-25s %-25s %-25s" "module=$MODULE" "license=$LIC" "supported=$SUP")"
				LIST_MODULES_ANY=$((LIST_MODULES_ANY + LIST_MODULE))
				wait_trace_off
			fi
		done
		if (( $LIST_MODULES_ANY == 0 )); then
			log_write $OF "Module List Unknown"
			log_write $OF
		fi
		log_cmd $OF "dmesg -T | grep taint"
	else
		log_write $OF "Kernel Status -- Not Tainted"
	fi
	log_write $OF

	PSPTMP=$(mktemp $LOG/psout.XXXXXXXX)
	AARPTMP=$(mktemp $LOG/security-aareject.XXXXXXXX)
	PSTMP=$(basename $PSPTMP)
	AARTMP=$(basename $AARPTMP)

	log_cmd $PSTMP 'ps axwwo user,pid,ppid,%cpu,%mem,vsz,rss,stat,time,cmd'

	log_write $OF "#==[ Checking Health of Processes ]=================#"
        log_write $OF "# awk '\$8 ~ /D|Z/' $PSPTMP"
        log_write $OF "$(awk '!/^#/ && $8 ~ /D|Z/' "$PSPTMP")"

	TOPTMP=$(mktemp $LOG/top.XXXXXXXX)
	log_write $OF
	log_write $OF "#==[ Summary ]======================================#"
	log_write $OF "# Top 10 CPU Processes"
	ps axwwo %cpu,pid,user,cmd | sort -k 1 -r -n | head -11 | sed -e '/^%/d' > $TOPTMP
	log_write $OF "%CPU   PID USER     CMD"
	log_write $OF "$(< $TOPTMP)"
	log_write $OF

	log_write $OF "#==[ Summary ]======================================#"
	log_write $OF "# Top 10 Memory Processes"
	ps axwwo %mem,pid,user,cmd | sort -k 1 -r -n | head -11 | sed -e '/^%/d' > $TOPTMP
	log_write $OF "%MEM   PID USER     CMD"
	log_write $OF "$(< $TOPTMP)"
	log_write $OF
	rm -f $TOPTMP

	if grep 'security=apparmor' /proc/cmdline &>/dev/null; then
		log_write $AARTMP "#==[ Summary ]======================================#"
		log_write $AARTMP "# AppArmor REJECT Messages"
		log_cmd $AARTMP 'systemctl status apparmor.service'

		APP_AUDIT_LOG="/var/log/audit/audit.log"
		[[ -f $APP_AUDIT_LOG ]] && AAREJECT=$(egrep 'REJECTING|DENIED' $APP_AUDIT_LOG | wc -l) || AAREJECT=0
		[[ -z "$AAREJECT" ]] && AAREJECT=0
		if [[ -x /usr/sbin/apparmor_status ]]; then
			/usr/sbin/apparmor_status --enabled &>/dev/null
			AASTAT=$?
			case $AASTAT in
			0) AALOADED="Loaded" ;;
			1) AALOADED="Disabled" ;;
			*) AALOADED="Loaded/Errors" ;;
			esac
		else
			AALOADED="Unknown"
		fi
		log_write $AARTMP
		log_write $AARTMP "${AAREJECT} Reject Messages, AppArmor Module: $AALOADED"
		log_write $AARTMP
	fi
	[[ -f $AARPTMP ]] && cat $AARPTMP >> $LOG/$OF

	MCE_LOG='/var/log/mcelog'
	FILES=$MCE_LOG
	if [[ -s $MCE_LOG ]]; then
		log_cmd $OF "ls -l --time-style=long-iso $MCE_LOG"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	fi

	cat $PSPTMP >> $LOG/$OF
	rm $PSPTMP

	echolog Done
}

rpm_info() {
	# This is a minimum required function, do not exclude
	printlog "RPM Database..."
	(( $MIN_OPTION_RPM )) || { echolog EXCLUDED; return 1; }
	addHeaderFile $RPMFILE
	if ((NSA_CHECK)); then
		log_write $RPMFILE "#==[ NSA Check ]====================================#"
		log_write $RPMFILE '# rpm -qa --queryformat "%-35{NAME} %-35{DISTRIBUTION} %{VERSION}-%{RELEASE}\n"'
		rpm -qa --queryformat "%-35{NAME} %-35{DISTRIBUTION} %{VERSION}-%{RELEASE}\n" >> $LOGFILE 2>&1
	else
		# rpm list of all files
		LOGFILE=$LOG/$RPM_DIST_FILE
		log_cmd $RPM_DIST_FILE 'rpm -qa --queryformat "%{DISTRIBUTION}\n" | sort | uniq'
		rpm -qa 2>/dev/null | sort > $LOG/$RPM_QA_FILE
		cat $LOG/$RPM_DIST_FILE >> $LOG/$RPMFILE
		log_cmd $RPMFILE "ls -l --time-style=long-iso /usr/local/bin /usr/local/sbin"
		log_write $RPMFILE "#==[ Command ]======================================#"
		log_write $RPMFILE '# rpm -qa --queryformat "%-35{NAME} %-35{DISTRIBUTION} %{VERSION}-%{RELEASE}\n" | sort -k 1,2 -t " " -i'
		printf "%-35s %-35s %s\n" NAME DISTRIBUTION VERSION >> $LOGFILE
		rpm -qa --queryformat "%-35{NAME} %-35{DISTRIBUTION} %{VERSION}-%{RELEASE}\n" | sort -k 1,2 -t " " -i >> $LOGFILE 2>&1
		log_write $RPMFILE
		log_cmd $RPMFILE "rpm -qa --last"
		log_write $RPMFILE "#==[ Command ]======================================#"
		log_write $RPMFILE '# rpm -qa --queryformat "%{SIGPGP:pgpsig}  %-35{VENDOR}  %{NAME}-%{VERSION}-%{RELEASE}\n" | sort -k 11 -t " " -i'
		printf "%-63s %-35s %s\n" SIGNATURE VENDOR PACKAGE >> $LOGFILE
		rpm -qa --queryformat "%{SIGPGP:pgpsig}  %-35{VENDOR}  %{NAME}-%{VERSION}-%{RELEASE}\n" | sort -k 11 -t " " -i >> $LOGFILE 2>&1
		log_write $RPMFILE
		# Jul 12, 2018 ; Added by Ahmad AL Zayed to get a list of RPM DB Backups 
		RETURN=$(grep RPMDB_BACKUP_DIR /etc/sysconfig/backup 2>/dev/null | grep -v "^#" | cut -d= -f2 | tr -d "\"")
		[[ -d $RETURN ]] && { log_cmd $RPMFILE "ls -ltr $RETURN" ;} 
	fi
	echolog Done
}

# Run basic_healthcheck first TAINT & TAINT_STRING must be defined first
module_info() {
	printlog "System Modules..."
	(( $OPTION_MOD )) || { echolog Excluded; return 1; }
	OF=modules.txt
	LOGFILE=$LOG/$OF
	addHeaderFile $OF
	log_cmd $OF 'lsmod | sort'
	for MODULE in $(cat /proc/modules | awk '{print $1}')
	do
		log_cmd $OF "modinfo $MODULE"
		MODPARM="/sys/module/$MODULE/parameters/"
		if [[ -d $MODPARM ]]; then
			log_write $OF "# Known Module Parameter Values"
			for i in $(ls -1 $MODPARM)
			do
				MODVALUE=$(cat ${MODPARM}$i 2>/dev/null)
				(( $? )) && MODVALUE="?"
				log_write $OF "${MODPARM}$i=$MODVALUE"
			done
			log_write $OF
		fi
		MODOPT=$(grep -R "options ${MODULE} " /etc/modprobe\.?* | grep -v ":# option")
		[[ -n "$MODOPT" ]] && { log_write $OF "# Module Configuration"; log_write $OF "$MODOPT"; log_write $OF; }
	done
	conf_files $OF /lib/modules/$(uname -r)/modules.*dep
	conf_files $OF /etc/modprobe.d/*
	echolog Done
}

messages_file() {
	# This is a minimum required function, do not exclude
	printlog "System Logs..."
	(( $MIN_OPTION_SYSLOGS )) || { echolog EXCLUDED; return 1; }
	OF=messages.txt
	OF2=messages_config.txt
	addHeaderFile $OF
	addHeaderFile $OF2
	if rpm_verify $OF2 rsyslog; then
		log_cmd $OF2 'systemctl status rsyslog.service'
		conf_files $OF2 /etc/rsyslog.conf /etc/rsyslog.d/remote.conf /etc/rsyslog.d/*.frule
		log_cmd $OF2 "rsyslogd -N 1"
	fi
	rpm_verify $OF2 systemd
	log_cmd $OF2 'systemctl status systemd-journald.service'
	JDIRS=''
	for JDIR in /etc/systemd/journald.conf.d/ /run/systemd/journald.conf.d/ /usr/lib/systemd/journald.conf.d/
	do
		[[ -d $JDIR ]] && JDIRS="$JDIRS $(find $JDIR -type f | grep 'conf$')"
	done
	conf_files $OF2 /etc/systemd/journald.conf $JDIRS

	MESSAGES_FILE="/var/log/messages"
	if [[ -s $MESSAGES_FILE ]]; then
		if (( $ADD_OPTION_LOGS )); then
			FILES="$(ls -1 /var/log/messages-[[:digit:]]* 2>/dev/null)"
			[[ -n "$FILES" ]] && log_entry $OF note "Additional Rotated Logs Included in the Tar Ball"
			log_files $OF 0 /var/log/messages
			for CMPLOG in $FILES
			do
				FILE=$(basename $CMPLOG)
				FILEROOT=${LOG}/$(cut -d\. -f1 <<< ${FILE})
				cp $CMPLOG ${LOG}
				FILE_TYPE=$(file --brief --mime-type $CMPLOG 2>/dev/null)
				case $FILE_TYPE in
				"text/plain")
				;;
				"application/x-xz")
					wait_trace_on "xz -d ${LOG}/$FILE"
					xz -d ${LOG}/$FILE
				;;
				"application/x-bzip2")
					wait_trace_on "bzip2 -d ${LOG}/$FILE"
					bzip2 -d ${LOG}/$FILE
				;;
				"application/x-gzip")
					wait_trace_on "gzip -d ${LOG}/$FILE"
					gzip -d ${LOG}/$FILE
				;;
	 			*)
					continue
				;;
				esac
				mv ${FILEROOT} ${FILEROOT}.txt
				wait_trace_off
			done
		else
			if (( $VAR_OPTION_MSG_MAXSIZE == 0 )); then
				log_files $OF 0 $MESSAGES_FILE  # override and get the entire file
			else
				MSGSIZE=$(stat -c%s $MESSAGES_FILE)
				if [[ $MSGSIZE -gt $VAR_OPTION_MSG_MAXSIZE ]]; then
					log_files $OF $VAR_OPTION_MSG_LINE_COUNT $MESSAGES_FILE # the file exceeded the max size allowed, get specified lines of the file
				else
					log_files $OF 0 $MESSAGES_FILE # get the whole file
				fi
			fi
		fi
	else
		if (( $ADD_OPTION_LOGS )); then
			log_cmd $OF "journalctl --no-pager --output=short-iso"
		else
			log_cmd $OF "journalctl --no-pager --output=short-iso --lines $VAR_OPTION_MSG_LINE_COUNT"
		fi
	fi
	echolog Done
}

localwarn_file() {
        printlog "Local/Warn Logs..."
        (( $MIN_OPTION_SYSLOGS )) || { echolog EXCLUDED; return 1; }
        OF=messages_localwarn.txt
        addHeaderFile $OF
        if (( $ADD_OPTION_LOGS )); then
                FILES="$(ls -1 /var/log/warn-[[:digit:]]* 2>/dev/null) $(ls -1 /var/log/localmessages-[[:digit:]]* 2>/dev/null)"
                [[ -n "$FILES" ]] && log_entry $OF note "Additional Rotated Logs Included in the Tar Ball"
                log_files $OF 0 /var/log/warn /var/log/localmessages
                for CMPLOG in $FILES
                do
                        FILE=$(basename $CMPLOG)
                        FILEROOT=${LOG}/$(cut -d\. -f1 <<< ${FILE})
                        cp $CMPLOG ${LOG}
                        FILE_TYPE=$(file --brief --mime-type $CMPLOG 2>/dev/null)
                        case $FILE_TYPE in
                        "text/plain")
                        ;;
                        "application/x-xz")
                                wait_trace_on "xz -d ${LOG}/$FILE"
                                xz -d ${LOG}/$FILE
                        ;;
                        "application/x-bzip2")
                                wait_trace_on "bzip2 -d ${LOG}/$FILE"
                                bzip2 -d ${LOG}/$FILE
                        ;;
                        "application/x-gzip")
                                wait_trace_on "gzip -d ${LOG}/$FILE"
                                gzip -d ${LOG}/$FILE
                        ;;
                        *)
                                continue
                        ;;
                        esac
                        mv ${FILEROOT} ${FILEROOT}.txt
                        wait_trace_off
                done
        else
                log_files $OF $VAR_OPTION_LINE_COUNT /var/log/warn
                LOGFILE="/var/log/localmessages"
                if [[ -e $LOGFILE ]]; then
                        if (( $VAR_OPTION_MSG_MAXSIZE == 0 )); then
                                log_files $OF 0 $LOGFILE  # override and get the entire file
                        else
                                MSGSIZE=$(stat -c%s $LOGFILE)
                                if [[ $MSGSIZE -gt $VAR_OPTION_MSG_MAXSIZE ]]; then
                                        log_files $OF $VAR_OPTION_MSG_LINE_COUNT $LOGFILE # the file exceeded the max size allowed, get specified lines of the file
                                else
                                        log_files $OF 0 $LOGFILE # get the whole file
                                fi
                        fi
                fi
        fi
        echolog Done
}


audit_info() {
	printlog "Auditing..."
	(( $OPTION_AUDIT )) || { echolog Excluded; return 1; }
	OF=security-audit.txt
	if rpm_verify $OF audit; then
		addHeaderFile $OF
		log_cmd $OF 'systemctl status auditd.service'
		log_cmd $OF 'auditctl -s'
		log_cmd $OF 'auditctl -l'
		log_cmd $OF 'aureport'
		if [[ -d /etc/audit ]]; then
			FILES=$(find -L /etc/audit/ -type f)
			if [[ -d /etc/audispd ]]; then
				FILES="$FILES $(find -L /etc/audispd/ -type f)"
			fi
		else
			FILES="/etc/auditd.conf /etc/audit.rules"
		fi
		conf_files $OF $FILES
		FILES=$(find /var/log/audit/ -type f | egrep -v "/ltaudit/" | grep log$)
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

yast_files() {
	# This is a minimum required function, do not exclude
	printlog "YaST Files..."
	(( $MIN_OPTION_YAST )) || { echolog EXCLUDED; return 1; }
	AGAMA_LOGFILE='/var/log/agama-installation/logs.tar.gz'
	hppsp_info
	# YaST files
	OF=y2log.txt
	addHeaderFile $OF
	rpm_verify $OF yast2-packager
	rpm_verify $OF yast2-packagemanager
	if rpm -q perl-Bootloader &> /dev/null; then
		rpm_verify $OF perl-Bootloader
	fi
	[[ -d /var/log/YaST2 ]] && FILES=$(find /var/log/YaST2/ -type f | egrep -v "_dev_|\.tbz$|\.tgz$|\.gz$|\.bz2$|\.zcat$|\.zip$") || unset FILES
	conf_files $OF /etc/youservers /etc/sysconfig/onlineupdate /etc/wgetrc 
	log_files $OF 0 /var/log/pbl.log
	(( ADD_OPTION_MAXYAST > 0 )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	[[ -s /root/autoupg.xml ]] && FILES="/root/autoupg*xml" || FILES=''
	conf_files $OF /root/autoinst.xml $FILES /var/adm/autoinstall/cache/installedSystem.xml
	[[ -f $AGAMA_LOGFILE ]] && log_cmd $OF "tar xf $AGAMA_LOGFILE -C $LOG"
	_sanitize_file $OF
	echolog Done
}

boot_info() {
	printlog "Boot Files..."
	(( $OPTION_BOOT )) || { echolog Excluded; return 1; }
	OF=boot.txt
	addHeaderFile $OF
	log_cmd $OF "uname -a"
	# Feb 6, 2024 - Ahmad Alzayed - Added grep -E '[0-9]' to avoid getting duplicated output
	KERNELS=$(cat $LOG/$RPMFILE | grep '^kernel-' | grep -v 'kernel-source' | awk '{print $1}' | grep -E '[0-9]')
	for KERNEL in $KERNELS
	do
		rpm_verify $OF $KERNEL
	done
	if rpm -q grub &> /dev/null; then
		rpm_verify $OF grub
		conf_files $OF /etc/grub.conf /boot/grub/menu.lst /boot/grub/device.map
		timed_log_cmd $OF 'hwinfo --framebuffer'
	fi
	if rpm -q grub2 &> /dev/null; then
		rpm_verify $OF grub2
		conf_files $OF /etc/default/grub /etc/default/grub_installdevice /boot/grub2/device.map
		BKOP=$ADD_OPTION_LOGS
		ADD_OPTION_LOGS=1 conf_files $OF /boot/grub2/grub.cfg
		ADD_OPTION_LOGS=$BKOP
	fi
	if rpm -q lilo &> /dev/null; then
		rpm_verify $OF lilo
		conf_files $OF /etc/lilo.conf /etc/yaboot.conf
	fi
	if rpm -q elilo &> /dev/null; then
		rpm_verify $OF elilo
		ELILOFILE=$(rpm -ql elilo | grep elilo.efi)
		ELILODIR=$(dirname $ELILOFILE)
		log_cmd $OF "ls -l --time-style=long-iso $ELILODIR"
		FILES="$(find /boot/ -type f 2>/dev/null | grep elilo.[conf,cfg]) $(find -L /etc/ -type f 2>/dev/null | grep elilo.[conf,cfg])"
		conf_files $OF $FILES
		log_cmd $OF "cksum $(ls -1 $ELILOFILE) $(find /boot/ -type f -name 'elilo.efi' 2>/dev/null)"
	fi
	if [[ -x /usr/sbin/bootlist ]]; then
		log_cmd $OF 'bootlist -m normal -o'
		log_cmd $OF 'bootlist -m normal -r'
	fi
	if rpm -q efibootmgr &> /dev/null; then
		log_cmd $OF "efibootmgr -v"
	fi
	if rpm -q mokutil &> /dev/null; then
		log_cmd $OF "mokutil --sb-state"
		log_cmd $OF "mokutil --list-sbat-revocations"
	fi
	if rpm -q s390-tools &> /dev/null; then
		conf_files $OF /etc/zipl.conf /boot/zipl/active_devices.txt /boot/zipl/config
	fi

	[[ -e /usr/sbin/mcelog ]] && log_cmd $OF "/usr/sbin/mcelog --ignorenodev --filter --dmi"
	[[ -s /var/log/mcelog ]] && { log_cmd $OF "ls -l --time-style=long-iso /var/log/mcelog"; conf_files $OF /var/log/mcelog; }
	log_cmd $OF 'last -wxF | egrep "reboot|shutdown|runlevel|system"'

	(( SLES_VER < 160 )) && FILES='/var/log/boot.log /etc/init.d/boot.local /etc/init.d/before.local /etc/init.d/after.local /etc/init.d/halt.local' || FILES=''
	conf_files $OF /proc/cmdline /etc/sysconfig/kernel $FILES

	log_cmd $OF 'ls -lR --time-style=long-iso /boot/'
	log_cmd $OF "lsinitrd -k $(uname -r)"
	(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	log_cmd $OF 'journalctl --no-pager --disk-usage'
	if (( $ADD_OPTION_LOGS )); then
		log_cmd $OF 'journalctl --no-pager --list-boot'
		LIST_BOOTS=$(journalctl --no-pager --list-boot | wc -l)
		((LIST_BOOTS--))
		if (( LIST_BOOTS > 0 )); then
			BOOT_COUNT=1
			if (( VAR_OPTION_JOURNALCTL_MAX_BOOTS > 0 )); then
				JOURNALCTL_MAX_BOOTS=$VAR_OPTION_JOURNALCTL_MAX_BOOTS
			else
				#VAR_OPTION_JOURNALCTL_MAX_BOOTS of 0 means get all boots
				JOURNALCTL_MAX_BOOTS=$LIST_BOOTS
			fi
			for THIS_BOOT in $(seq 0 $LIST_BOOTS)
			do
				log_cmd $OF "journalctl --no-pager --boot $THIS_BOOT"
				((BOOT_COUNT < JOURNALCTL_MAX_BOOTS)) && ((BOOT_COUNT++)) || break
			done
		else
			log_cmd $OF "journalctl --no-pager --boot 0"
		fi
	else
		if (( VAR_OPTION_JOURNALCTL_LINE_COUNT > 0 )); then
			log_cmd $OF "journalctl --no-pager --boot 0 | tail -n ${VAR_OPTION_JOURNALCTL_LINE_COUNT}"
		else
			log_cmd $OF "journalctl --no-pager --boot 0"
		fi
	fi
	log_cmd $OF 'dmesg -T'
	_sanitize_file $OF
	echolog Done
}

bpf_info() {
	printlog "BPF..."
	# Berkley Packet Filter facility (BPF)
	(( $OPTION_BPF )) || { echolog Excluded; return 1; }
	OF=bpf.txt
	addHeaderFile $OF
	bpf_present=$(zgrep 'CONFIG_BPF=y' /proc/config.gz)
	if [[ "$bpf_present" ]]; then
		if rpm_verify $OF bpftool; then
			log_cmd $OF 'grep -E bpf_prog_[a-f0-9]{16} /proc/kallsyms'
			for bpfsub in prog map net
			do
				log_cmd $OF "bpftool $bpfsub list";
			done
			log_cmd $OF 'bpftool cgroup tree';
			log_cmd $OF 'bpftool struct_ops dump';

			for bpfid in $(bpftool prog list | grep -E '^[0-9]+:' | cut -d: -f1)
			do
				log_cmd $OF "bpftool prog dump xlated id $bpfid"
			done
			if (( $INCLUDE_NETWORK_NAMESPACES )); then
				NAMESPACES=$(ip netns list)
				if [[ -n "${NAMESPACES}" ]]; then
					ip netns list | while read NAMESPACE rest; do
						log_cmd $OF "ip netns exec ${NAMESPACE} bpftool net list"
					done
				fi
			fi
		else
			log_cmd $OF 'grep -E bpf_prog_[a-f0-9]{16} /proc/kallsyms'
		fi
		echolog Done
	else
		echolog Skipped
	fi
}
smt_info() {
	printlog "SMT..."
	(( $OPTION_SMT )) || { echolog Excluded; return 1; }
	OF=smt.txt
	addHeaderFile $OF
	if rpm_verify $OF smt; then
		log_cmd $OF 'systemctl status smt.service'
		CONF=/etc/smt.conf
		conf_files $OF /etc/smt.conf
		FILES=$(find -L /etc/smt.d/ -type f 2>/dev/null)
		conf_files $OF $FILES
		log_cmd $OF 'smt-catalogs'
		log_cmd $OF 'smt-catalogs -o'
		log_cmd $OF 'smt-list-registrations'
		log_cmd $OF 'smt-list-products'
		if [[ -d /srv/www/htdocs/repo ]]; then
			log_cmd $OF 'find /srv/www/htdocs/repo -print0 | sort -z | xargs -0 ls -ld --time-style=long-iso'
		fi
		FILES=$(find /var/log/ -type f | grep smt- | grep log$)
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		_sanitize_file $OF
		echolog Done
	else
		echolog Skipped
	fi
}

update_info() {
	printlog "Updates..."
	(( $OPTION_UP )) || { echolog Excluded; return 1; }
	OF=updates.txt
	SKIP=0
	TIMEOUT=0
	addHeaderFile $OF
	if rpm_verify $OF zypper; then
		log_cmd $OF 'date'
		log_cmd $OF 'ls -lA --time-style=long-iso /etc/products.d/'
		log_cmd $OF 'zypper locks'
		log_cmd $OF 'zypper patterns --installed-only'
		for CMDOPT in services 'repos -d' patch-check patches list-patches list-updates products '--xmlout products' 'packages --orphaned'
		do
			if (( $TIMEOUT >= 10 )); then
				log_write $OF "#==[ Command ]======================================#"
				log_write $OF "# Skipped \"zypper $CMDOPT\" due to previous timeout"
				log_write $OF
			else
				timed_log_cmd $OF "zypper --non-interactive --no-gpg-checks $CMDOPT"
				TIMEOUT=$?
			fi
		done
		rpm_verify $OF lsb
		conf_files $OF /etc/zypp/zypp.conf /etc/zypp/credentials.d/NCCcredentials
	fi
	if rpm -q suseconnect-ng &> /dev/null; then
		if rpm_verify $OF suseconnect-ng
		then
			log_cmd $OF "SUSEConnect --status"
			FILES=$(find -L /etc/zypp/credentials.d/ -type f 2>/dev/null)
			conf_files $OF /etc/SUSEConnect $FILES
		fi
	elif rpm -q SUSEConnect &> /dev/null; then
		if rpm_verify $OF SUSEConnect
		then
			rpm_verify $OF ruby2.1-rubygem-suse-connect
			log_cmd $OF "SUSEConnect --status"
			FILES=$(find -L /etc/zypp/credentials.d/ -type f 2>/dev/null)
			conf_files $OF /etc/SUSEConnect $FILES
		fi
	fi
	
	if rpm -q zypper-lifecycle-plugin &> /dev/null; then
		log_cmd $OF 'zypper lifecycle'
	fi

	if rpm -q libzypp &> /dev/null; then
		QPBIN=$(rpm -ql libzypp | grep query-pool)
		[[ -n "$QPBIN" ]] && timed_log_cmd $OF "$QPBIN products" || ((SKIP++))
	elif rpm -q libzypp-zmd-backend &> /dev/null; then
		QPBIN=$(rpm -ql libzypp-zmd-backend | grep query-pool)
		[[ -n "$QPBIN" ]] && timed_log_cmd $OF "$QPBIN products" || ((SKIP++))
	fi

	if rpm -q zypper &> /dev/null; then
		log_cmd $OF 'installation_sources -s'
	fi

	log_cmd $OF "env | grep -i proxy | grep -v CMDLINE"
	conf_files $OF /etc/sysconfig/proxy
	if [[ -s /root/.curlrc ]]; then
		conf_files $OF /root/.curlrc
		SC_PROXY_PASS=$(grep -i "^proxy-user" /root/.curlrc | sed -e 's/"//g' | awk '{print $3}' | cut -d\: -f2)
		sed -i -e "s/:${SC_PROXY_PASS}$/:*REMOVED BY SUPPORTCONFIG*/g;s/:${SC_PROXY_PASS}\"$/:*REMOVED BY SUPPORTCONFIG*\"/g" $LOG/$OF
	fi

	if rpm -q curl &>/dev/null; then
		# Test update server
		UPDATE_TEST_URL=''
		if [[ -s /etc/sysconfig/rhn/up2date ]]; then # get SUMA update URL
			UPDATE_TEST_URL=$( cat /etc/sysconfig/rhn/up2date | grep -i "^serverURL=" | cut -d= -f2)
		elif [[ -s /etc/SUSEConnect ]]; then # get SLE12 update URL
			UPDATE_TEST_URL=$( cat /etc/SUSEConnect | grep -i "^url: " | awk '{print $2}')
		elif [[ -s /etc/suseRegister.conf ]]; then # get SLE11 update URL
			UPDATE_TEST_URL=$( cat /etc/suseRegister.conf | grep -i "^url=" | cut -d= -f2)
		fi

		if [[ -n $UPDATE_TEST_URL ]]; then # a local update server URL was found
			if echo $UPDATE_TEST_URL | egrep -i "^http.*//" &>/dev/null; then
				LOCAL_TEST_PROTOCOL=$(echo $UPDATE_TEST_URL | awk -F/ '{print $1}')
				LOCAL_TEST_HOST=$(echo $UPDATE_TEST_URL | awk -F/ '{print $3}')
			else
				LOCAL_TEST_PROTOCOL=''
				LOCAL_TEST_HOST=$(echo $UPDATE_TEST_URL | awk -F/ '{print $1}')
			fi
			if [[ -n LOCAL_TEST_PROTOCOL ]]; then
				LOCAL_TEST_URL="${LOCAL_TEST_PROTOCOL}//${LOCAL_TEST_HOST}/"
			else
				LOCAL_TEST_URL="${UPDATE_TEST_HOST}"
			fi
			log_cmd $OF "curl --connect-timeout 10 --trace-ascii ${LOG}/updates-curl-trace_${LOCAL_TEST_HOST}.txt --digest --remote-time --fail ${LOCAL_TEST_URL}"
		else # no local update server URL found
			if (( ADD_OPTION_LOCAL_ONLY )); then
				log_entry $OF note "curl -- aborted: ADD_OPTION_LOCAL_ONLY set, no local update URLs found"
			else
				for SUSE_TEST_URL in 'https://updates.suse.com/' 'https://scc.suse.com/'
				do
					SUSE_TEST_HOST=$(echo $SUSE_TEST_URL | awk -F/ '{print $3}')
					log_cmd $OF "curl --connect-timeout 10 --trace-ascii ${LOG}/updates-curl-trace_${SUSE_TEST_HOST}.txt --digest --remote-time --fail $SUSE_TEST_URL"
				done
			fi
		fi
	else
		log_entry $OF note "curl -- not installed, aborted"
	fi

	FILES='/var/log/zypp/history'
	FILES="$FILES $(find /var/log/ -type f -name \*zypp\*)"
	(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES

	conf_files $OF '/proc/kgr_in_progress'
	log_entry $OF note "Processes blocking kGraft patching"
	FOUND=0
	for i in $(find /proc -type f 2> /dev/null | grep -i kgr_in_progress)
	do
		VAL=$(cat $i 2>/dev/null)
		if [[ -n "$VAL" ]]
		then
			PPATH=$(dirname $i)
			if (( VAL > 0 ))
			then
				COMM=$(cat ${PPATH}/comm 2>/dev/null)
				KPID=$(basename ${PPATH})
				log_write $OF "$KPID: $COMM"
				FOUND=1
			fi
		fi
	done
	(( FOUND )) && log_write $OF

	_sanitize_file $OF
	echolog Done
}

pam_info() {
	printlog "PAM..."
	OF=pam.txt
	addHeaderFile $OF
	if (( $FORCE_OPTION_PAM > 0 )); then
		rpm_verify $OF pam
		rpm_verify $OF pam-modules
		conf_files $OF /etc/nsswitch.conf /etc/nologin
		conf_files $OF /etc/passwd
		log_cmd $OF 'getent passwd'
		conf_files $OF /etc/group
		log_cmd $OF 'getent group'
		EXTRA_DIRS=$(egrep '^#includedir |^@includedir ' /etc/sudoers | awk '{print $NF}')
		conf_files $OF /etc/sudoers
		for EXTRA in $EXTRA_DIRS
		do
			conf_files $OF ${EXTRA}/*
		done

		log_cmd $OF 'loginctl --no-pager list-sessions'
		log_write $OF "#==[ Files in /etc/security ]=======================#"
		[[ -d /etc/security ]] && FILES="$(find -L /etc/security/ -type f -name \*conf)" || FILES=""
		conf_files $OF $FILES
		# Nov 24, 2023 ,, Added by Ahmad Alzayed
		log_cmd $OF "ls -lt --time-style=long-iso /etc/pam.d/"
		log_write $OF "#==[ Files in /etc/pam.d ]==========================#"
		[[ -d /etc/pam.d ]] && FILES="$(find -L /etc/pam.d/ -type f | sort)" || FILES=""
		conf_files $OF $FILES
		echolog Done
	else
		log_entry $OF note "Restricted"
		echo "PAM module is disabled in compliance with General Data Protection Regulation (GDPR)." >> $LOG/$OF
		echo "To consent to supportconfig collecting this information, run:" >> $LOG/$OF
		echo "# FORCE_OPTION_PAM=1 supportconfig" >> $LOG/$OF
		echo >> $LOG/$OF
		echo 'Additional info: https://www.suse.com/support/kb/doc/?id=000019695' >> $LOG/$OF
		echo >> $LOG/$OF
		echolog Restricted
	fi
}

sssd_info() {
	printlog "System Security Services..."
	(( $OPTION_SSSD )) || { echolog Excluded; return 1; }
	OF=sssd.txt
	addHeaderFile $OF
	if rpm_verify $OF sssd; then
		rpm_verify $OF sssd-tool
		rpm_verify $OF python-sssd-config
		log_cmd $OF 'systemctl status sssd.service'
		conf_files $OF "/etc/nsswitch.conf /etc/sssd/sssd.conf"
		log_cmd $OF 'ls -l --time-style=long-iso /etc/sssd/sssd.conf'
		log_cmd $OF 'ls -lR --time-style=long-iso /etc/sssd/conf.d/'
		if [[ -d /etc/sssd/conf.d ]]; then
			FILES=$(find -L /etc/sssd/conf.d/ -type f | egrep "\.conf$")
			conf_files $OF "$FILES"
		fi
		SRVS_LDAP=$(grep "^[[:space:]]*ldap_uri" /etc/sssd/sssd.conf | cut -d= -f2 | sed -e 's/ *//g;s/,/ /g')
		if [[ -n "$SRVS_LDAP" ]]; then
			for URI in $SRVS_LDAP
			do
				ADDR=$(echo $URI | awk -F\/ '{print $NF}' | cut -d\: -f1)
				ping_addr $OF 'SSSD LDAP Server' $ADDR
			done
		fi
		SRVS_KRB5=$(egrep "^[[:space:]]*krb5_server|^[[:space:]]*krb5_kdcip" /etc/sssd/sssd.conf | cut -d= -f2 | sed -e 's/ *//g;s/,/ /g')
		if [[ -n "$SRVS_KRB5" ]]; then
			for URI in $SRVS_KRB5
			do
				ADDR=$(echo $URI | awk -F\/ '{print $NF}' | cut -d\: -f1)
				ping_addr $OF 'SSSD Kerberos Server' $ADDR
			done
		fi
		log_cmd $OF 'date +"%Y-%m-%d %H:%M"'
		log_cmd $OF 'ls -lR --time-style=long-iso /var/lib/sss/'
		SSSD_PID=$(systemctl show sssd.service -p ExecMainPID)
		SSSD_PID=${SSSD_PID#ExecMainPID=}
		if (( $SSSD_PID )); then
			SSSD_PIDS=$(ps axwwo pid,ppid,cmd | grep ${SSSD_PID} | grep -v grep | awk '{print $1}' | sort -n)
			log_cmd $OF "ps axwwo user,pid,ppid,%cpu,%mem,vsz,rss,stat,time,cmd | egrep \"${SSSD_PID}|PPID\" | grep -v grep"
			for THISPID in $SSSD_PIDS
			do
				log_cmd $OF "lsof -b -n -l +fg -P -p $THISPID 2>/dev/null"
			done
		fi
		log_cmd $OF 'grep pam_sss /etc/pam.d/*'
		FILES="/var/log/sssd/*"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files ' sssd' $OF 0 $FILES || grep_log_files ' sssd' $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

environment_info() {
	printlog "Environment..."
	(( $OPTION_ENV )) || { echolog Excluded; return 1; }
	OF=env.txt
	addHeaderFile $OF
	log_icmd $OF 'ulimit -a'
	log_cmd $OF 'systemctl status systemd-sysctl.service'
	conf_files $OF /etc/sysctl.conf /boot/sysctl.conf-* /lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf
	log_cmd $OF 'sysctl -a'
	log_cmd $OF 'getconf -a'
	log_cmd $OF 'ipcs -l'
	log_cmd $OF 'ipcs -a'
	log_cmd $OF 'CASAcli -l'
	[[ -d /etc/default ]] && FILES=$(find -L /etc/default/ -type f) || FILES=""
	conf_files $OF $FILES /root/.xauth/export
	log_cmd $OF 'env'
	# s390 specific
	if [[ -e /dev/vmcp ]]; then
		log_cmd $OF 'vmcp query virtual all'
		log_cmd $OF 'vmcp query privclass'
		log_cmd $OF 'vmcp query cplevel'
		log_cmd $OF 'vmcp query mdc'
		log_cmd $OF 'vmcp query qioassist'
		log_cmd $OF 'vmcp query files'
		log_cmd $OF 'vmcp query userid'
	else
		case $ARCH in
		s390x) 
			log_write $OF "#==[ s390x Hardware Detected ]======================#"
			log_write $OF "# Consider loading vmcp for more info: modprobe vmcp"
			log_write $OF
			;;
		esac
	fi
	conf_files $OF /etc/profile /etc/profile.local /etc/profile.d/*
	conf_files $OF /etc/bash.bashrc /etc/csh\.* /etc/ksh*
	sed -i -e 's/\r//g' $LOG/$OF
	echolog Done
}

systemd_info() {
	printlog "SystemD..."
	(( $OPTION_DAEMONS )) || { echolog Excluded; return 1; }
	OF=systemd.txt
	OF2=systemd-status.txt
	addHeaderFile $OF
	addHeaderFile $OF2
	rpm_verify $OF systemd
	log_cmd $OF 'hostnamectl status'
	log_cmd $OF 'systemctl --failed'
	log_cmd $OF 'busctl --no-pager --system list'
	log_cmd $OF 'timedatectl --no-pager status'
	log_cmd $OF 'systemd-analyze --no-pager blame'
	log_cmd $OF 'systemd-cgtop --batch --iterations=1'
	log_cmd $OF 'systemd-cgls --no-pager --all --full'
	log_cmd $OF 'systemd-delta --no-pager'
	FILES=''
	[[ -d /etc/systemd ]] && FILES=$(find -L /etc/systemd -maxdepth 1 -type f)
	log_cmd $OF 'systemctl --no-pager show | sort'
	conf_files $OF $FILES
	log_cmd $OF 'systemctl --no-pager --all list-units'
	log_cmd $OF 'systemctl --no-pager --all list-sockets'
	log_cmd $OF 'systemctl --no-pager list-unit-files'
	log_cmd $OF 'systemctl --no-pager list-jobs'
	log_cmd $OF 'systemctl --no-pager list-timers --all'
	for i in $(systemctl --no-pager --all list-units | sed 's/^[^-_:\\a-zA-Z0-9]*//' | egrep -v '^UNIT |^LOAD |^ACTIVE |^SUB |^To |^[[:digit:]]* ' | awk '{print $1}')
	do
		if [[ -z "$i" ]]
		then
			break
		else
			log_cmd $OF "systemctl show '$i' | sort"
		fi
	done
	for i in $(systemctl --no-pager list-units --type=service | grep -v "not-found" | sed 's/^[^-_:\\a-zA-Z0-9]*//' | egrep -v '^UNIT |^LOAD |^ACTIVE |^SUB |^To |^[[:digit:]]* ' | awk '{print $1}')
	do
		log_cmd $OF2 "systemctl status '$i'"
	done
	log_cmd $OF 'ls -alR /etc/systemd/'
	log_cmd $OF 'ls -alR /usr/lib/systemd/'
	echolog Done
}

docker_info() {
	printlog "Docker..."
	(( $OPTION_DOCKER )) || { echolog Excluded; return 1; }
	OF=docker.txt
	addHeaderFile $OF
	DOCKERSCDIR=$LOG/docker
	[[ -e /usr/bin/docker ]] && DOCKER_PKG=`rpm -q --whatprovides /usr/bin/docker 2>/dev/null`
	[[ -z $DOCKER_PKG ]] && DOCKER_PKG='docker'
	if rpm_verify $OF $DOCKER_PKG
	then
		log_cmd $OF 'systemctl status docker.service'
		log_cmd $OF 'docker version'
		log_cmd $OF 'docker info'
		log_cmd $OF 'docker images'
		log_cmd $OF 'docker ps --all'
		log_cmd $OF 'docker network ls'
		FILES=('/etc/sysconfig/docker' '/etc/docker/daemon.json')
		conf_files $OF $FILES
		if rpm_verify $OF ruby2.1-rubygem-sle2docker
		then
			log_cmd $OF 'sle2docker version'
			log_cmd $OF 'sle2docker list'
		fi
		mkdir -p $DOCKERSCDIR
		for container in $(docker ps -a --format "{{.ID}}" 2>/dev/null);
		do
			CONTAINEROF=docker/"$container".txt
			log_cmd $CONTAINEROF "docker top $container"
			log_cmd $CONTAINEROF "docker inspect $container"
			log_cmd $CONTAINEROF "docker logs --timestamps $container"
		done
		log_cmd $OF 'ls -al --time-style=long-iso /var/lib/docker/containers'
		log_cmd $OF 'journalctl -u docker'
	fi
	echolog Done
}

plymouth_info() {
	printlog "Plymouth..."
	(( $OPTION_PLYMOUTH )) || { echolog Excluded; return 1; }
	OF=plymouth.txt
	addHeaderFile $OF
	plymouth_configs="/etc/plymouth/plymouthd.conf /usr/share/plymouth/plymouthd.defaults /etc/logrotate.d/bootlog"
	plymouth_themes="bgrt breeze-text breeze details fade-in script solar spinfinity spinner text tribar"
	plymouth_logs="/var/log/plymouth-debug.log /var/log/plymouth-shutdown-debug.log /var/lib/plymouth/boot-duration /var/log/boot.log"

	for plymouth_pkgs in `rpm -qa | grep 'plymouth\|libply' | xargs echo`
	do
		rpm_verify $OF $plymouth_pkgs
	done
	conf_files $OF $plymouth_configs

	for theme in ${plymouth_themes[@]}; do
		theme_config=/usr/share/plymouth/themes/$theme/$theme.plymouth
		[[ -e $theme_config ]] && conf_files $OF $theme_config
	done

	log_files $OF 0 $plymouth_logs
	echolog Done
}

podman_info() {
	printlog "Podman..."
	(( $OPTION_PODMAN )) || { echolog Excluded; return 1; }
	ROOTOF="podman-root.txt"
	PODMANSCDIR=$LOG/podman
	[[ -e /usr/bin/podman ]] && PODMAN_PKG=$(rpm -q --whatprovides /usr/bin/podman 2>/dev/null) || PODMAN_PKG='podman'
	if rpm_verify $ROOTOF $PODMAN_PKG
	then
		mkdir -p $PODMANSCDIR
		# Identify all non-root users currently running at least one container
		PODMAN_USERS_ACTIVE=$(ps axwwo user,cmd | grep conmon | grep -v grep | cut -d\  -f1 | sort | uniq | grep -v root)

		# Include any LOCAL_PODMAN_USERS defined in supportconfig.conf
		declare -A PODMAN_DICT
		for USER in $PODMAN_USERS_ACTIVE
		do
			PODMAN_DICT[$USER]=1
		done
		for USER in $LOCAL_PODMAN_USERS
		do
			PODMAN_DICT[$USER]=1
		done
		PODMAN_USERS="root ${!PODMAN_DICT[@]}"
		unset PODMAN_DICT USER PODMAN_USERS_ACTIVE

		CURRENT_DIR=$(pwd)
		cd /tmp
		for PODMAN_USER in $PODMAN_USERS
		do
			OF="podman-${PODMAN_USER}.txt"
			addHeaderFile $OF
			if id ${PODMAN_USER} &> /dev/null; then
				[[ "${PODMAN_USER}" == "root" ]] && PODACC='' || PODACC="sudo -u ${PODMAN_USER} "
				ACCESS_PODMAN_USER=1
				if log_cmd $OF "${PODACC}podman version"; then
					log_cmd $OF "${PODACC}podman info"
					log_cmd $OF "${PODACC}podman images"
					for image in $(${PODACC}podman images --format="{{.Repository}}_{{.Tag}}_{{.ID}}" 2>/dev/null)
					do
						image=$(basename $image)
						IMAGEOF="podman/${PODMAN_USER}-image-${image}.txt"
						IMAGEID=${image##*_}
						log_entry $OF note "Image details: $IMAGEOF"
						log_cmd $IMAGEOF "${PODACC}podman images | egrep \"^REPO|${IMAGEID}\""
						log_cmd $IMAGEOF "${PODACC}podman inspect ${IMAGEID}"
					done

					log_cmd $OF "${PODACC}podman ps --all --pod"
					for container in $(${PODACC}podman ps -a --format="{{.Names}}" 2>/dev/null)
					do
						CONTAINEROF="podman/${PODMAN_USER}-container-${container}.txt"
						log_entry $OF note "Container details: $CONTAINEROF"
						log_cmd $CONTAINEROF "${PODACC}podman ps --all --pod | egrep \"^CONTAINER|${container}\""
						log_cmd $CONTAINEROF "${PODACC}podman top $container"
						log_cmd $CONTAINEROF "${PODACC}podman inspect $container"
						log_cmd $CONTAINEROF "${PODACC}podman logs --timestamps $container"
					done
					log_cmd $OF "${PODACC}podman network ls"
					for podnet in $(${PODACC}podman network ls --format "{{.Name}}")
					do
						log_cmd $OF "${PODACC}podman network inspect ${podnet}"
					done
					log_cmd $OF "${PODACC}podman volume ls"
					for podvol in $(${PODACC}podman volume ls --format "{{.Name}}")
					do
						log_cmd $OF "${PODACC}podman volume inspect ${podvol}"
					done
					log_cmd $OF "${PODACC}podman pod list"
					for this_pod in $(${PODACC}podman pod list --format "{{.Name}}")
					do
						PODOF="podman/${PODMAN_USER}-pod-${this_pod}.txt"
						log_entry $OF note "Pod details: $PODOF"
						log_cmd $PODOF "${PODACC}podman pod ls | egrep \"^POD|${this_pod}\""
						log_cmd $PODOF "${PODACC}podman pod inspect ${this_pod}"
					done
				else
					ACCESS_PODMAN_USER=0
				fi
				PODMAN_USER_HOME=''
				PODMAN_USER_HOME=$(${PODACC}env | grep "^HOME" | cut -d= -f2)
				[[ -n $PODMAN_USER_HOME ]] && PODMAN_USER_CONFIG="${PODMAN_USER_HOME}/.config/containers" || PODMAN_USER_CONFIG=''
				[[ -z $PODACC ]] && FILES=$(find -L /etc/containers -type f) || FILES=''
				if [[ -d $PODMAN_USER_CONFIG ]]; then
					FILES="${FILES} $(find -L $PODMAN_USER_CONFIG -type f)"
				fi
				[[ -n $FILES ]] && conf_files $OF $FILES
				if (( $ACCESS_PODMAN_USER )); then
					if (( $ADD_OPTION_LOGS )); then
						log_cmd $OF "${PODACC}podman events --since 0 --stream=false"
					fi
				fi
			else
				log_cmd $OF "id ${PODMAN_USER}"
			fi
		done

		cd $CURRENT_PATH
		echolog Done
	else
		echolog Skipped
	fi
}

cron_info() {
	printlog "CRON..."
	test $OPTION_CRON -eq 0 && { echolog Excluded; return 1; }
	OF=cron.txt
	addHeaderFile $OF
	if rpm_verify $OF cronie
	then
		log_cmd $OF "systemctl status cron.service"
		conf_files $OF /var/spool/cron/allow /var/spool/cron/deny
		log_write $OF "### Individual User Cron Jobs ###"
		test -d /var/spool/cron/tabs && FILES=$(find /var/spool/cron/tabs/ -type f) || FILES=""
		conf_files $OF $FILES
		CRONS="cron.d cron.hourly cron.daily cron.weekly cron.monthly"
		log_write $OF "### System Cron Job File List ###"
		for CRONDIR in $CRONS
		do
			log_cmd $OF "find -L /etc/${CRONDIR}/ -type f"
		done
		log_write $OF "### System Cron Job File Content ###"
		conf_files $OF /etc/crontab
		for CRONDIR in $CRONS
		do
			FILES=$(find -L /etc/${CRONDIR}/ -type f)
			conf_files $OF $FILES
		done
		echolog Done
	else
		echolog Skipped
	fi
	printlog "AT..."
	log_write $OF "#----------------------------------------------------------------#"
	if rpm_verify $OF at
	then
		log_cmd $OF "systemctl status atd.service"
		log_write $OF "### System at Job File List ###"
		log_cmd $OF "find /var/spool/atjobs/ -type f"
		log_write $OF "### System at Job File Content ###"
		FILES=$(find /var/spool/atjobs/ -type f)
		conf_files $OF $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

dbus_info() {
	printlog "D-Bus..."
	(( $OPTION_DBUS )) || { echolog Excluded; return 1; }
	OF=dbus.txt
	addHeaderFile $OF
	RPM_PKGS=$(egrep "^dbus" $RPM_QA_FILE_PATH)
	if rpm_verify $OF "$RPM_PKGS"
	then
		log_cmd $OF 'systemctl status dbus.socket'
		log_cmd $OF 'systemctl status dbus.service'
	fi
	DBUS_CONF_DIR="/usr/share/dbus-1/system.d/"
	[[ -d $DBUS_CONF_DIR ]] && CFILES=$(find $DBUS_CONF_DIR -type f -name \*.conf) || CFILES=''
	conf_files $OF /usr/share/dbus-1/system-local.conf /usr/share/dbus-1/system.conf /usr/share/dbus-1/session.conf $CFILES
	log_cmd $OF 'ls -lR --time-style=long-iso /usr/share/dbus-1/'
	echolog Done
}

soft_raid_info() {
	printlog "Software Raid..."
	(( $OPTION_SRAID )) || { echolog Excluded; return 1; }
	OF=fs-softraid.txt
	addHeaderFile $OF
	conf_files $OF /proc/mdstat
	if rpm_verify $OF mdadm
	then
		log_cmd $OF 'mdadm --detail --scan'
	fi
	if rpm_verify $OF raidtools
	then
		LOGFILE=$LOG/$OF
		for MDEVICE in $(cat /proc/mdstat | grep ^md | awk '{print $1}')
		do
			echo "# lsraid -a /dev/$MDEVICE" >> $LOGFILE
			lsraid -a /dev/$MDEVICE >> $LOGFILE 2>&1
			echo >> $LOGFILE
		done
	fi
	conf_files $OF /etc/mdadm.conf /etc/raidtab
	echolog Done
}

lvm_info() {
	printlog "LVM..."
	(( $OPTION_LVM )) || { echolog Excluded; return 1; }
	echonlog "Please Wait..."
	OF=lvm.txt
	local LVM_IO_DELAYS=0
	addHeaderFile $OF
	if rpm_verify $OF lvm2
	then
		echonlog Base
		VGBIN="vgs"
		LVBIN="lvs"
		log_cmd $OF 'systemctl status lvm2-activation-early.service'
		FILES="/etc/lvm/lvm.conf"

		# suppress lvm command warnings about FD leaks
		# see man(8) lvm
		export LVM_SUPPRESS_FD_WARNINGS=1

		timed_log_cmd $OF 'pvs' || LVM_IO_DELAYS=1
		if ! (( $LVM_IO_DELAYS )); then
			log_cmd $OF "vgs"
			log_cmd $OF "lvs"
		fi
		conf_files $OF $FILES
		log_cmd $OF 'dmsetup ls --tree'
		log_cmd $OF 'dmsetup table'
		log_cmd $OF 'dmsetup info'
		log_cmd $OF 'ls -l --time-style=long-iso /etc/lvm/backup/'
		conf_files $OF /etc/lvm/backup/*
		log_cmd $OF 'ls -l --time-style=long-iso /etc/lvm/archive/'
		conf_files $OF /etc/lvm/archive/*
		if ! (( $LVM_IO_DELAYS )); then
			echonlog Detail
			log_write $OF
			log_write $OF "###[ Detail Scans ]###########################################################################"
			log_write $OF
			log_cmd $OF 'pvdisplay -vv'
			log_cmd $OF 'vgdisplay -vv'
			log_cmd $OF 'lvdisplay -vv'
			log_cmd $OF 'pvs -vvvv'
			log_cmd $OF 'pvscan -vvv'
			log_cmd $OF "$VGBIN -vvvv"
			log_cmd $OF "$LVBIN -vvvv"
		fi
		unset LVM_SUPPRESS_FD_WARNINGS
		echolog Done
	else
		echolog Skipped
	fi
}

mpio_info() {
	printlog "Multipathing..."
	(( $OPTION_MPIO )) || { echolog Excluded; return 1; }
	OF=mpio.txt
	addHeaderFile $OF
	SKIP=0
	MPIO_RPM=$(rpm -qf `which multipath 2>/dev/null` 2>/dev/null)
	if [[ -z "$MPIO_RPM" ]]; then
		MPIO_RPM=multipath-tools
	fi
	if rpm_verify $OF $MPIO_RPM
	then
		log_cmd $OF 'systemctl status multipathd.service'
		log_cmd $OF 'systemctl status multipathd.socket'
		log_cmd $OF 'lspci -b'
		log_cmd $OF 'multipath -ll'
		log_cmd $OF 'ls -lR --time-style=long-iso /dev/disk/'
		MPIO_FILES=$(find /etc/multipath/ -type f 2>/dev/null)
		conf_files $OF /etc/multipath.conf $MPIO_FILES /etc/modprobe.conf.local /etc/sysconfig/hotplug /etc/sysconfig/kernel /etc/fstab
		log_cmd $OF 'lsscsi -g'
		log_cmd $OF 'dmsetup ls --tree'
		log_cmd $OF 'dmsetup table'
		log_cmd $OF 'dmsetup info'
		log_cmd $OF 'lspath'
		log_cmd $OF 'lsmap -all'
		log_cmd $OF 'lsnports'
		log_cmd $OF "udevadm info -e"
		[[ -d /proc/scsi ]] && SCSI_DIRS=$(find /proc/scsi/ -type d) || SCSI_DIRS=""
		for SDIR in $SCSI_DIRS
		do
			# Skip unwanted scsi directories
			[[ "$SDIR" == "/proc/scsi" ]] || [[ "$SDIR" == "/proc/scsi/sg" ]] || [[ "$SDIR" == "/proc/scsi/mptspi" ]] && continue
			FILES=$(find ${SDIR}/ -maxdepth 1 -type f 2>/dev/null)
			conf_files $OF $FILES
		done
		log_cmd $OF 'multipath -t'
		log_cmd $OF 'multipath -v3 -d'
	else
		((SKIP++))
	fi
	if rpm_verify $OF EMCpower.LINUX
	then
		[[ -x /sbin/powermt ]] && log_cmd $OF 'powermt display dev=all'
	else
		((SKIP++))
	fi
	(( $SKIP < 2 )) && echolog Done || echolog Skipped
}

detectProducts() {
	OUT=$1
	if rpm -q SLES_SAP-release &>/dev/null
	then
		log_write $OUT "#==[ System ]=======================================#"
		log_write $OUT "# Product"
		log_write $OUT "SUSE Linux Enterprise Server for SAP Applications"
		log_write $OUT
	fi
}

detectVirtualization() {
	OUT=$1
	log_write $OUT "#==[ System ]=======================================#"
	log_write $OUT "# Virtualization"
	NO_HYPER=1
	if [[ -x /usr/sbin/dmidecode ]]; then
		MANUFACTURERNAME=$(/usr/sbin/dmidecode -s system-manufacturer 2>/dev/null)
		SYSPRODNAME=$(/usr/sbin/dmidecode -s system-product-name 2>/dev/null)
		if [[ -n "$MANUFACTURERNAME" ]]; then
			log_write $OUT "Manufacturer:  $MANUFACTURERNAME"
			log_write $OUT "Hardware:      $SYSPRODNAME"
		else
			log_write $OUT "Hardware:      See hardware.txt"
		fi
	else
		log_write $OUT "Hardware:      See hardware.txt"
	fi
	if [[ -x /usr/bin/lscpu ]]; then
		LSCPU_OUT=$(/usr/bin/lscpu 2>/dev/null | egrep -i "virtualization|hypervisor")
	else
		LSCPU_OUT=''
	fi

	# Xen Hypervisor
	if [[ -e /sys/hypervisor/type ]] && [[ -e /sys/hypervisor/uuid ]]; then
		HYPER_TYPE=$(cat /sys/hypervisor/type | tr '[A-Z]' '[a-z]')
		if [[ "$HYPER_TYPE" == "xen" ]]; then
			NO_HYPER=0
			XEN_UUID=$(cat /sys/hypervisor/uuid | tr -d '-')
			IDENT=$(egrep -i "Virtualization type" <<< $LSCPU_OUT | awk '{print $NF}')
			log_write $OUT "Hypervisor:    Xen"
			if [[ $XEN_UUID =~ [[:alpha:]] ]]; then
					log_write $OUT "Identity:      Virtual Machine - DomU"
			else
					log_write $OUT "Identity:      Virtual Machine Server - Dom0"
			fi
			case $IDENT in
			'full')
				log_write $OUT "Type:          Fully Virtualized"
				;;
			'para')
				log_write $OUT "Type:          Para Virtualized"
				;;
			esac
		fi
	fi

	# KVM Hypervisor
	if grep -iq "Virtualization:" <<< $LSCPU_OUT; then
		if grep -iq "Hypervisor vendor.*KVM" <<< $LSCPU_OUT; then
			NO_HYPER=0
			log_write $OUT "Hypervisor:    KVM"
			log_write $OUT "Identity:      Virtual Machine - DomU"
			IDENT=$(egrep -i "Virtualization type" <<< $LSCPU_OUT | awk '{print $NF}')
			case $IDENT in
			'full')
				log_write $OUT "Type:          Fully Virtualized"
				;;
			*)
				log_write $OUT "Identity:      Unknown"
				;;
			esac
		elif systemctl is-enabled libvirtd.service &>/dev/null; then
			NO_HYPER=0
			log_write $OUT "Hypervisor:    KVM"
			log_write $OUT "Identity:      Virtual Machine Server - Dom0"
		fi
	fi

	# VMware Hypervisor
	if grep '^vmmon' /proc/modules &>/dev/null; then
		NO_HYPER=0
		log_write $OUT "Hypervisor:    VMware (vmmon loaded)"
		log_write $OUT "Identity:      Virtual Machine Server (Not vmware hardware platform)"
	elif echo $SYSPRODNAME | grep -i vmware &>/dev/null; then
		NO_HYPER=0
		log_write $OUT "Hypervisor:    VMware (hardware platform)"
		if rpm -q "SLES-for-VMware-release" &>/dev/null; then
			log_write $OUT "Identity:      Virtual Machine (SLES for VMware)"
		else
			log_write $OUT "Identity:      Virtual Machine (hardware platform)"
		fi
	fi

	# Microsoft Virtual Server Hypervisor
	if echo $MANUFACTURERNAME | grep -i microsoft &>/dev/null; then
		NO_HYPER=0
		log_write $OUT "Hypervisor:    Microsoft (manufacturer)"
		log_write $OUT "Identity:      Virtual Machine (hardware)"
	fi

	# Sun VirtualBox Hypervisor
	if grep '^vboxdrv' /proc/modules &>/dev/null; then
		NO_HYPER=0
		log_write $OUT "Hypervisor:    Sun VirtualBox (vboxdrv loaded)"
		log_write $OUT "Identity:      Virtual Machine Server (Not VirtualBox hardware platform)"
	elif echo $SYSPRODNAME | grep -i VirtualBox &>/dev/null; then
		NO_HYPER=0
		log_write $OUT "Hypervisor:    Sun VirtualBox (hardware platform)"
		log_write $OUT "Identity:      Virtual Machine (hardware platform)"
	fi

	if (( NO_HYPER )); then
		log_write $OUT "Hypervisor:    None"
		log_write $OUT "Identity:      Not Detected"
	fi

	log_write $OUT
}

hardware_info() {
	# This is a minimum required function, do not exclude
	printlog "Hardware..."
	(( $MIN_OPTION_HARDWARE )) || { echolog EXCLUDED; return 1; }
	echonlog "Please Wait..."
	OF=hardware.txt
	addHeaderFile $OF
	log_cmd $OF 'lscpu'
	detectVirtualization $OF
	conf_files $OF /proc/cpuinfo /proc/cmdline /proc/ioports /proc/dma /proc/devices /proc/bus/usb/devices
	log_cmd $OF 'lspci -b'
	log_cmd $OF 'cpupower frequency-info'
	log_cmd $OF 'cpupower idle-info'
	log_cmd $OF 'cpupower info'
	if ! (( $MIN_OPTION_AUTOMOD )); then
		log_write $OF "#==[ Warning ]======================================#"
		log_write $OF "# Autoloading kernel modules disabled. Don't use -k."
		log_write $OF "# Excluding hwinfo"
		log_write $OF
		log_cmd $OF 'biosdecode'
	else
		PROBE_VALUES='-braille,-pppoe'
		log_entry $OF note "export hwprobe=\"${PROBE_VALUES}\""
		export hwprobe="${PROBE_VALUES}"
		timed_log_cmd $OF "hwinfo --all --log=${LOG}/${HWINFO_FILE}"
		log_files $OF 0 ${LOG}/${HWINFO_FILE}
	fi
	log_cmd $OF 'dmidecode'
	log_cmd $OF 'lspci -nn'
	log_cmd $OF 'lspci -vvv'
	log_cmd $OF 'lsusb -vv'
	log_cmd $OF 'ls -al /dev | egrep "fd.*|dvd.*|cdr.*"'
	ALSABIN='/usr/sbin/alsa-info.sh'
	if [[ -x $ALSABIN ]]; then
			log_cmd $OF "$ALSABIN --stdout --no-upload --with-configs --with-devices --with-dmesg --with-alsactl"
	fi

	if [[ "$ARCH" == "s390x" ]]; then
		log_cmd $OF 'read_values -s'
	fi

	if grep ppc64 <<< $ARCH &> /dev/null #Readded from previous commit, including it now.
	then
		platform=""
		if grep PowerNV /proc/cpuinfo &> /dev/null; then
			platform="PowerNV"
		elif grep pSeries /proc/cpuinfo &> /dev/null; then
			platform="pSeries"
		fi

		if rpm -q powerpc-utils &>/dev/null; then
			rpm_verify $OF powerpc-utils
			log_cmd $OF "ppc64_cpu --smt"
			log_cmd $OF "ppc64_cpu --cores-present"
			log_cmd $OF "ppc64_cpu --cores-on"
			log_cmd $OF "ppc64_cpu --run-mode"
			log_cmd $OF "ppc64_cpu --frequency"
			log_cmd $OF "ppc64_cpu --dscr"
			log_cmd $OF "nvram --print-config"
			if [[ $platform == "pSeries" ]]; then
				log_cmd $OF "serv_config -l"
				log_cmd $OF "bootlist -m both -r"
				log_cmd $OF "lparstat -i"
				log_cmd $OF "lparnumascore"
				log_cmd $OF "lparnumascore -c cpu -d 4"
				log_cmd $OF "lparnumascore -c mem -d 3"
			fi
		fi
		if rpm -q lsvpd &>/dev/null; then
			rpm_verify $OF lsvpd
			log_cmd $OF "lscfg -vp"
			log_cmd $OF "lsmcode -A"
			log_cmd $OF "lsvpd --debug"
			if [[ $platform == "pSeries" ]]; then
				log_cmd $OF "lsvio -des"
			fi
		fi

		if rpm -q ppc64-diag &>/dev/null; then
			rpm_verify $OF ppc64-diag
			log_cmd $OF "usysattn"
			log_cmd $OF "usysident"
			log_cmd $OF "diag_encl -v"
			log_cmd $OF "opal-elog-parse -s"
			log_cmd $OF "opal-elog-parse -a"
			log_cmd $OF "opal-elog-parse -l"
		fi

		if rpm -q iprutils &>/dev/null; then
			rpm_verify $OF iprutils
			log_cmd $OF "iprconfig -c show-config"
			log_cmd $OF "iprconfig -c show-alt-config"
			log_cmd $OF "iprconfig -c show-arrays"
			log_cmd $OF "iprconfig -c show-jbod-disks"
			log_cmd $OF "iprconfig -c show-ioas"
			log_cmd $OF "iprconfig -c show-hot-spares"
			log_cmd $OF "iprconfig -c show-af-disks"
			log_cmd $OF "iprconfig -c show-all-af-disks"
			log_cmd $OF "iprconfig -c show-slots"
			log_cmd $OF "iprconfig -c dump"
		fi
		if [[ $platform == "pSeries" ]]; then
			if rpm -q servicelog &>/dev/null; then
				rpm_verify $OF servicelog
				log_cmd $OF "servicelog --dump"
				log_cmd $OF "servicelog_notify --list"
			fi

			log_cmd $OF 'lssrc -a'
			log_cmd $OF 'lsdevinfo'
			log_cmd $OF 'lsslot'
			log_cmd $OF 'amsstat'
			log_cmd $OF 'lsrsrc IBM.MCP'
			log_cmd $OF 'rmcdomainstatus -s ctrmc'
			log_cmd $OF 'rmcdomainstatus -s ctrmc -a ip'
			log_cmd $OF 'systemctl status ctrmc.service -l'
			log_cmd $OF 'systemctl is-enabled hcn-init.service'
			log_files $OF 0 /var/log/hcnmgr /var/ct/IBM.DRM.stderr /var/ct/IW/log/mc/IBM.DRM/trace*
		fi

		PPC_DIR="${LOG}/ppc64"
		mkdir -p $PPC_DIR
		case $platform in
		"pSeries")
			log_entry $OF command "cp /proc/ppc64/eeh /proc/ppc64/lparcfg /proc/ppc64/systemcfg /var/log/platform /dev/nvram $PPC_DIR"
			cp /proc/ppc64/eeh /proc/ppc64/lparcfg /proc/ppc64/systemcfg /var/log/platform /dev/nvram $PPC_DIR 2>/dev/null

			if rpm -q rsct.core.utils &>/dev/null; then
				CTSNAP_DIR="${PPC_DIR}/ctsnap"
				mkdir -p $CTSNAP_DIR
				log_cmd $OF "ctsnap -xrunrpttr -d $CTSNAP_DIR"
			fi

			if [[ -f /etc/ct_node_id ]]; then
				log_entry $OF command "cp /etc/ct_node_id $PPC_DIR"
				cp /etc/ct_node_id $PPC_DIR 2>/dev/null
			fi

			if [[ -f /var/log/drmgr ]]; then
				log_entry $OF command "cp /var/log/drmgr $PPC_DIR"
				cp /var/log/drmgr $PPC_DIR 2>/dev/null
			fi
			if [[ -f /var/log/drmgr.0 ]]; then
				log_entry $OF command "cp /var/log/drmgr.0 $PPC_DIR"
				cp /var/log/drmgr.0 $PPC_DIR 2>/dev/null
			fi
			if [[ -f /sys/kernel/debug/dynamic_debug/control ]]; then
				log_entry $OF command "cp /sys/kernel/debug/dynamic_debug/control $PPC_DIR"
				cp /sys/kernel/debug/dynamic_debug/control $PPC_DIR 2>/dev/null
			fi

			if [[ -f /var/log/rtas_errd.log ]]; then
				log_entry $OF command "cp /var/log/rtas_errd.log $PPC_DIR"
				cp /var/log/rtas_errd.log $PPC_DIR 2>/dev/null
			fi

			if rpm -q IBMinvscout &>/dev/null; then
				log_cmd $OF "invscout"
				log_cmd $OF "invscout -v"
				log_entry $OF command "cp -r /var/adm/invscout $PPC_DIR"
				cp -r /var/adm/invscout $PPC_DIR 2>/dev/null
			fi
			;;
		"PowerNV")
			log_entry $OF command "cp /proc/ppc64/eeh /proc/ppc64/systemcfg /proc/ppc64/topology_updates /sys/firmware/opal/msglog /var/log/opal-elog /dev/nvram $PPC_DIR"
			cp /proc/ppc64/eeh /proc/ppc64/systemcfg /proc/ppc64/topology_updates /sys/firmware/opal/msglog /var/log/opal-elog /dev/nvram $PPC_DIR 2>/dev/null
			;;
		esac

		if [[ -f /var/log/lp_diag.log ]]; then
			log_entry $OF command "cp /var/log/lp_diag.log $PPC_DIR"
			cp /var/log/lp_diag.log $PPC_DIR 2>/dev/null
		fi

		if [[ -d /proc/device-tree/ ]]; then
			SAVE_DIR="${PPC_DIR}/device-tree"
			mkdir -p $SAVE_DIR
			log_entry $OF command "cp -r /proc/device-tree/* $SAVE_DIR"
			cp -r /proc/device-tree/* $SAVE_DIR 2>/dev/null
		fi

                if [[ -d /sys/fs/pstore/ ]]; then
                        SAVE_DIR="${PPC_DIR}/pstore"
                        mkdir -p $SAVE_DIR
                        log_entry $OF command "cp -r /sys/fs/pstore/* $SAVE_DIR"
                        cp -r /sys/fs/pstore/* $SAVE_DIR 2>/dev/null
                fi

		if [[ -d /var/log/dump ]]; then
			log_cmd $OF "ls -l /var/log/dump"
		fi
	fi
	[[ "$(systemctl show nvidia-persistenced.service -p LoadState)" == "LoadState=not-found" ]] || log_cmd $OF "systemctl status nvidia-persistenced.service"
	echolog Done
}

net_info() {
	printlog "Networking..."
	(( $OPTION_NET )) || { echolog Excluded; return 1; }
	if (( $INCLUDE_NETWORK_NAMESPACES )); then
		NAMESPACES=$(ip netns list)
		if [[ -n "${NAMESPACES}" ]]; then
			net_info_namespace "network.txt" 
			ip netns list | while read NAMESPACE rest; do
				net_info_namespace "network-${NAMESPACE}.txt" "${NAMESPACE}"
			done
		else
			net_info_namespace "network.txt" 
		fi
	else
		net_info_namespace "network.txt" 
	fi
	echolog Done
}

net_info_namespace() {
	OF=$1
	addHeaderFile $OF
	if [[ -z "${2}" ]]; then
		NS=""
	else 
		NS="ip netns exec $2 "
		log_write $OF "#==[ Network namespace ${2} ]======================#"
	fi
	if [[ -z "${NS}" ]]; then
		if (( SLES_VER >= 160 )); then
			rpm_verify $OF NetworkManager
			rpm_verify $OF iproute2
			rpm_verify $OF firewalld && FIREWALL=1 || FIREWALL=0
			log_cmd $OF "systemctl status network.service"
			if (( FIREWALL )); then
				log_cmd $OF 'systemctl status firewalld.service'
			fi
			log_cmd $OF "ip netns list"
			log_cmd $OF 'nmcli general status'
			log_cmd $OF 'nmcli device show'
			log_cmd $OF 'nmcli connection show'
			CONNECTIONS=$(nmcli -f NAME connection show | grep -v NAME)
			while read LINE; do log_cmd $OF "nmcli connection show \"$LINE\""; done <<< "$CONNECTIONS"
			EFILES=$(find /etc/NetworkManager /usr/lib/NetworkManager -type f | grep -v ' ')
			conf_files $OF $EFILES
		elif (( SLES_VER >= 150 )); then
			rpm_verify $OF sysconfig
			rpm_verify $OF wicked
			rpm_verify $OF iproute2
			rpm_verify $OF firewalld && log_cmd $OF "systemctl status firewalld.service"
			log_cmd $OF "systemctl status network.service"
			log_cmd $OF "systemctl status nscd.service"
			log_cmd $OF "wicked ifstatus --verbose all"
			log_cmd $OF "ip netns list"
			log_cmd $OF "wicked show-config"
		fi
	fi
	log_cmd $OF "${NS}ip addr"
	log_cmd $OF "${NS}ip route"
	log_cmd $OF "${NS}ip -6 route"
	log_cmd $OF "${NS}ip -stats link"
	log_cmd $OF "${NS}ip -stats neighbor"
	if [[ -z "${NS}" ]]; then
		(( $MIN_OPTION_AUTOMOD )) && timed_log_cmd $OF 'hwinfo --netcard'
		conf_files $OF /proc/sys/net/ipv4/ip_forward /etc/HOSTNAME
		log_cmd $OF "${NS}hostname"
		# s390 specific
		if grep vmcp /proc/modules &>/dev/null; then
			log_cmd $OF "vmcp query nic details"
			log_cmd $OF "vmcp query lan details"
			log_cmd $OF "vmcp query vswitch detail"
		else
			case $ARCH in
			s390x) 
				log_write $OF "#==[ s390x Hardware Detected ]======================#"
				log_write $OF "# Consider loading vmcp for more info: modprobe vmcp"
				log_write $OF
				;;
			esac
		fi
	fi
	IPADDRS=$(${NS}ip addr | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)
	for IPADDR in $IPADDRS
	do
		ping_addr $OF 'Local Interface' $IPADDR "${NS}"
	done

	IPADDR=$(${NS}ip route list | awk '$1 == "default" {print $3}')
	ping_addr $OF 'Default Route' $IPADDR "${NS}"

	if [[ -z "${NS}" ]]; then
		[[ -e /etc/resolv.conf ]] && IPADDRS=$(grep ^nameserver /etc/resolv.conf | awk '{print $2}') || IPADDRS=""
		for IPADDR in $IPADDRS
		do
			ping_addr $OF 'DNS Server' $IPADDR "${NS}"
		done
	fi

	${NS}ip rule show | while read skip skip skip skip table rest
	do
		log_cmd $OF "${NS}ip route show table $table"
	done
	log_cmd $OF "${NS}ip route show table cache"
	log_cmd $OF "${NS}ip -6 route show table cache"
	log_cmd $OF "${NS}ip rule show"
	NICS=$(IFS="@: ";${NS}ip -o l | while read number nic dummy ; do echo $nic ; done)
	for NIC in ${NICS}
	do
		log_cmd $OF "${NS}tc -s -d qdisc show dev ${NIC}"
		log_cmd $OF "${NS}tc -s -d class show dev ${NIC}"
		log_cmd $OF "${NS}tc -s -d filter show dev ${NIC}"
	done
	log_cmd $OF "${NS}ss -s"
	log_cmd $OF "${NS}ss -nap"
	log_cmd $OF "${NS}ip ntable show"
	log_cmd $OF "${NS}nstat -az"
	if ! (( $MIN_OPTION_AUTOMOD )); then
		log_write $OF "#==[ Warning ]======================================#"
		log_write $OF "# Autoloading kernel modules disabled. Don't use -k."
		log_write $OF "# Excluding IPsec command: xfrm"
		log_write $OF
	else
		log_cmd $OF "${NS}ip xfrm state list"
		log_cmd $OF "${NS}ip xfrm policy list"
	fi
	log_cmd $OF "${NS}ip maddr show"
	log_cmd $OF "${NS}ip mroute show"

	if ! (( $MIN_OPTION_AUTOMOD )); then
		log_write $OF "#==[ Warning ]======================================#"
		log_write $OF "# Autoloading kernel modules disabled. Don't use -k."
		log_write $OF "# Excluding Bridge command: brctl"
		log_write $OF
	else
		if [[ -x /sbin/brctl ]]; then
			log_cmd $OF "${NS}brctl show"
			for BRIDGE in `${NS}brctl show | sed 1d | awk '{print$1}'`
			do 
				log_cmd $OF "${NS}brctl showmacs $BRIDGE"
			done
		fi
	fi
	ETHTOOL_BIN=$(which ethtool 2>/dev/null)
	if [[ -x $ETHTOOL_BIN ]]; then
		NICS=$(IFS="@: ";${NS}ip -o l | while read number nic dummy ; do echo $nic ; done)
		for NIC in ${NICS}
		do
			log_cmd $OF "${NS}${ETHTOOL_BIN} ${NIC}"
			for OPTION in k i S g l m -show-fec -show-eee -show-ntuple -show-coalesce
			do
				log_cmd $OF "${NS}${ETHTOOL_BIN} -${OPTION} ${NIC}"
			done
		done
	fi
	if [[ -z "${NS}" ]]; then
		log_cmd $OF "nscd -g"
		conf_files $OF /etc/hosts /etc/host.conf /etc/resolv.conf /etc/nsswitch.conf /etc/nscd.conf /etc/hosts.allow /etc/hosts.deny /etc/sysconfig/firewalld
	fi
	log_cmd $OF "${NS}firewall-cmd --list-all"
	log_cmd $OF "${NS}firewall-cmd --list-all-zones"
	log_cmd $OF "${NS}firewall-cmd --list-all-policies"
	# do not collect inside namespace
	[[ -z "$2" && -d /etc/firewalld/zones ]] && FILES=$(find -L /etc/firewalld/zones | grep '\.xml$') || FILES=""
	conf_files $OF $FILES
	for TABLE in filter nat mangle raw
	do
		if grep iptable_$TABLE /proc/modules &>/dev/null
		then
			log_cmd $OF "${NS}iptables -t $TABLE -nvL"
			log_cmd $OF "${NS}iptables-save -t $TABLE"
		else
			log_entry $OF command "iptables"
			log_write $OF "# NOTE: The iptable_$TABLE module is not loaded, skipping check"
			log_write $OF
		fi
	done
	for TABLE in filter nat mangle raw
	do
		if grep ip6table_$TABLE /proc/modules &>/dev/null
		then
			log_cmd $OF "${NS}ip6tables -t $TABLE -nvL"
			log_cmd $OF "${NS}ip6tables-save -t $TABLE"
		else
			log_entry $OF command "ip6tables"
			log_write $OF "# NOTE: The ip6table_$TABLE module is not loaded, skipping check"
			log_write $OF
		fi
	done

	IPVSADM_BIN=$(command -v ipvsadm)
	if [[ -x $IPVSADM_BIN ]]; then
		log_cmd $OF "${NS}${IPVSADM_BIN} -Ln"
	fi

	IPSET_BIN=$(command -v ipset)
	if [[ -x $IPSET_BIN ]]; then
		log_cmd $OF "${NS}${IPSET_BIN} list"
	fi

	if rpm_verify $OF nftables
	then
		log_cmd $OF "${NS}nft list tables"

		# playing around with IFS is unfortunately necessary here for
		# properly parsing the 'nft list tables' output and the standard
		# IFS must be used to avoid breaking the namespace passed to log_cmd
		SAVEIFS=$IFS
		IFS=$(echo -ne "\n\b")
		for NF_TABLE in $(${NS}nft list tables | cut -d\  -f2,3)
		do
			IFS=$SAVEIFS
			log_cmd $OF "${NS}nft list table $NF_TABLE"
			IFS=$(echo -ne "\n\b")
		done
		IFS=$SAVEIFS
	fi

	if [[ -z "${NS}" ]]; then
		[[ -d /etc/sysconfig/network ]] && FILES=$(find /etc/sysconfig/network/ -maxdepth 1 -type f) || FILES=""
		conf_files $OF /etc/sysconfig/proxy $FILES 
		(( SLES_VER < 160 )) && FILES=$(find /etc/wicked -type f 2>/dev/null | grep '\.xml$') || FILES=''
		conf_files $OF $FILES
		if [[ -d /proc/net/bonding ]]; then
			FILES=$(find /proc/net/bonding/ -type f)
			conf_files $OF $FILES 
		fi
		conf_files $OF /usr/etc/services
		FILES=$(grep logfile /etc/nscd.conf 2> /dev/null | grep -v ^# | awk '{print $2}' | tail -1)
		[[ -n "$FILES" ]] || FILES="/var/log/nscd.log"
		FILES="$FILES /var/log/NetworkManager"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	fi
	_sanitize_file $OF
}

disk_info() {
	printlog "Disk I/O..."
	(( $OPTION_DISK )) || { echolog Excluded; return 1; }
	OF=fs-diskio.txt
	addHeaderFile $OF
	conf_files $OF /proc/partitions /etc/fstab
	(( $IO_DELAYS )) || log_cmd $OF "df -Th"
	log_cmd $OF "lsblk -i -o 'NAME,KNAME,MAJ:MIN,FSTYPE,LABEL,RO,RM,MODEL,SIZE,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,MOUNTPOINT,DISC-ALN,DISC-GRAN,DISC-MAX,DISC-ZERO'"
	log_cmd $OF "blkid"
	[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt"
	log_cmd $OF "mount"
	conf_files $OF /proc/mounts /etc/mtab

	for DISK in $(cat /proc/partitions | grep -v ^m | grep -v ^$ | awk '{print $4}')
	do
		case $DISK in
		sd[a-z]|sd[a-z][a-z]) log_cmd $OF "parted -s /dev/$DISK unit s print" ;;
		hd[a-z]|hd[a-z][a-z]) log_cmd $OF "parted -s /dev/$DISK unit s print" ;;
		xvd[a-z]|xvd[a-z][a-z]) log_cmd $OF "parted -s /dev/$DISK unit s print" ;;
		dasd[a-z]|dasd[a-z][a-z]) 
			log_cmd $OF "dasdview -i /dev/$DISK"
			log_cmd $OF "dasdview -t info /dev/$DISK"
			;;
		cciss*) 
			CCISS_DISK=$(echo $DISK | cut -d/ -f2)
			case $CCISS_DISK in
			c[0-9]d[0-9]) log_cmd $OF "parted -s /dev/cciss/$CCISS_DISK unit s print" ;;
			esac
			CCISS_DISK=$(echo $DISK | cut -d\! -f2)
			case $CCISS_DISK in
			c[0-9]d[0-9]) log_cmd $OF "parted -s /dev/cciss/$CCISS_DISK unit s print" ;;
			esac
			;;
		esac
	done

	log_cmd $OF 'ls -lR --time-style=long-iso /dev/disk/'
	log_cmd $OF 'ls -l --time-style=long-iso /dev/mapper/'
	log_cmd $OF 'ls -l --time-style=long-iso /sys/block/'
	log_cmd $OF 'lslocks'
	log_cmd $OF 'ls -l /dev/disk/by-path/'
	log_cmd $OF 'ls -l /dev/disk/by-id/'
	log_cmd $OF 'ls -l /dev/disk/by-uuid/'
	log_cmd $OF "grep '' /sys/block/*/queue/scheduler"

	if ! (( $ADD_OPTION_MINDISK )); then
		log_cmd $OF 'iostat -x 1 4'
		log_cmd $OF 'sg_map -i -x'
		if [[ -d /sys/block ]]; then
			IDE_DISKS=$(find /sys/block/ -maxdepth 1 | grep hd\.)
			SCSI_DISKS=$(find /sys/block/ -maxdepth 1 | grep sd\.)
			CCISS_DISKS=$(find /sys/block/ -maxdepth 1 | grep cciss\*)
		else
			IDE_DISKS=""
			SCSI_DISKS=""
			CCISS_DISKS=""
		fi


		if [[ -n "$IDE_DISKS" ]] && [[ -d /proc/ide ]]; then
			log_write $OF "#==[ IDE Detailed Info ]============================#"
			log_write $OF "#---------------------------------------------------#"
			FILES=$(find /proc/ide/ -maxdepth 1 -type f 2>/dev/null)
			conf_files $OF $FILES
			if rpm_verify $OF hdparm
			then
				DISKS=$(find /proc/ide/ -maxdepth 1 | grep hd\. | sort)
				for DISK in $DISKS
				do
					CURRENT_DISK="/dev/$(basename $DISK)"
					log_cmd $OF "hdparm -vi $CURRENT_DISK"
				done
			fi
		fi

		if [[ -n "$SCSI_DISKS" ]]; then
			log_write $OF "#==[ SCSI Detailed Info ]===========================#"
			log_write $OF "#---------------------------------------------------#"
			log_cmd $OF 'lsscsi'
			log_cmd $OF 'lsscsi -H'
			if log_cmd $OF 'scsiinfo -l'
			then
				FILES=$(scsiinfo -l)
				for DEVICE in $FILES
				do
					log_cmd $OF "scsiinfo -i $DEVICE"
				done
			fi
			log_cmd $OF 'lsscsi -v'
			[[ -d /proc/scsi ]] && SCSI_DIRS=$(find /proc/scsi/ -type d) || SCSI_DIRS=""
			for SDIR in $SCSI_DIRS
			do
				[[ "$SDIR" == "/proc/scsi" ]] || [[ "$SDIR" == "/proc/scsi/sg" ]] || [[ "$SDIR" == "/proc/scsi/mptspi" ]] && continue
				FILES=$(find ${SDIR}/ -maxdepth 1 -type f 2>/dev/null)
				conf_files $OF $FILES
			done
		fi

		if [[ -n "$CCISS_DISKS" ]] && [[ -d /proc/driver/cciss ]]; then
			log_write $OF "#==[ CCISS Detailed Info ]==========================#"
			log_write $OF "#---------------------------------------------------#"
			FILES=$(find /proc/driver/cciss/ -maxdepth 1 -type f 2>/dev/null)
			conf_files $OF $FILES
		fi
		if ! (( $IO_DELAYS )); then
			DISKS=$(sfdisk -l 2>/dev/null | grep -i 'disk /' | awk '{print $2}' | sed -e 's/://g')
			if [[ -n $DISKS ]]; then
				for DISK in $DISKS
				do
					log_cmd $OF "sfdisk -d $DISK"
				done
			fi
		fi
	fi
        if [[ "$ARCH" == "s390x" ]]; then
               log_write $OF "#==[ s390x and DASD Info ]==========================#"
               log_write $OF "#---------------------------------------------------#"
               log_cmd $OF 'lsdasd -a'
               log_cmd $OF 'lsdasd --long'
               log_cmd $OF 'rpm -V s390-tools'
        fi

	echolog Done
}

btrfs_info() {
	printlog "B-tree File System..."
	(( $OPTION_BTRFS )) || { echolog Excluded; return 1; }
	OF=fs-btrfs.txt
	if rpm_verify $OF btrfsprogs; then
		addHeaderFile $OF
		log_cmd $OF "btrfs filesystem show"
		conf_files $OF /etc/fstab
		[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt" || log_cmd $OF "mount"
		(( $IO_DELAYS )) || log_cmd $OF "df -Th"
		log_cmd $OF "modinfo btrfs"
		for DEVICE in $(btrfs filesystem show | awk 'NF{ print $NF }' | grep ^/)
		#TODO For multi-device btrfs filesysems only use one device
		do
			for FILESYS in $(findmnt -S $DEVICE --types btrfs --list --output target --first-only --noheadings)
			do
				log_cmd $OF "btrfs filesystem usage $FILESYS"
				log_cmd $OF "btrfs scrub status $FILESYS"
				log_cmd $OF "btrfs balance status -v $FILESYS"
				log_cmd $OF "btrfs subvolume get-default $FILESYS"
				log_cmd $OF "btrfs subvolume list $FILESYS"
				log_cmd $OF "btrfs qgroup show -prce $FILESYS"
				log_cmd $OF "btrfs device stats $FILESYS"
			done
		done

		if rpm_verify $OF snapper; then
			log_cmd $OF "snapper list-configs"
			CONFIGS=$(snapper --table-style 0 list-configs | sed -e 's/[[:space:]]*//g;1,2d')
			for PAIR in $CONFIGS
			do
				CONFIG=$(echo $PAIR | cut -d\| -f1)
				log_cmd $OF "snapper -c $CONFIG list"
			done
			conf_files $OF /etc/sysconfig/snapper /etc/snapper/configs/* /etc/snapper/filters/*
		fi
                FILES="/var/log/messages"
                (( $ADD_OPTION_LOGS )) && grep_log_files btrfs $OF 0 $FILES || grep_log_files btrfs $OF $VAR_OPTION_LINE_COUNT $FILES

		FILES="/var/log/snapper.log"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

iscsi_info() {
	printlog "iSCSI..."
	(( $OPTION_ISCSI )) || { echolog Excluded; return 1; }
	OF=fs-iscsi.txt
	addHeaderFile $OF
	FILES=''
	log_write $OF "#___________________________________________________________#"
	log_write $OF "#____[ iSCSI Target Information ]___________________________#"
	log_write $OF
	if rpm_verify $OF python3-targetcli-fb
	then
		log_cmd $OF 'systemctl status targetcli.service'
		log_cmd $OF 'lsmod | grep target_'
		log_cmd $OF 'targetcli ls'
		[[ -d /etc/target ]] && FILES=$(find -L /etc/target -type f)
	fi
	conf_files $OF $FILES

	log_write $OF "#___________________________________________________________#"
	log_write $OF "#____[ iSCSI Initiator Information ]________________________#"
	log_write $OF
	if rpm_verify $OF open-iscsi
	then
		log_cmd $OF 'systemctl status iscsi.service'
		log_cmd $OF 'systemctl status iscsid.service'
		log_cmd $OF 'systemctl status iscsid.socket'
		conf_files $OF "/etc/iscsi/initiatorname.iscsi /etc/iscsi/iscsid.conf"
		for MODE in discovery iface host session
		do
			log_cmd $OF "iscsiadm -m $MODE"
			log_cmd $OF "iscsiadm -m $MODE -P 1"
		done
		log_cmd $OF 'iscsiadm -m fw'
		if log_cmd $OF 'iscsiadm -m node'
		then
			log_cmd $OF 'iscsiadm -m node -P 1'
			NODES=$(iscsiadm -m node -P 1 | grep -i Target | awk '{print $2}')
			IBIN='iscsiadm -m node -T'
			for NODE in $NODES
			do
				log_cmd $OF "$IBIN $NODE"
			done
		fi
	fi
	_sanitize_file $OF
	echolog Done
}

nfs_info() {
	printlog "NFS..."
	(( $OPTION_NFS )) || { echolog Excluded; return 1; }
	OF=nfs.txt
	addHeaderFile $OF
	NFS_FOUND=0
	if rpm_verify $OF nfs-client
	then
		rpm_verify $OF rpcbind
		log_cmd $OF 'systemctl status nfs.service'
		log_cmd $OF 'systemctl status rpcbind.service'
		conf_files $OF /etc/nfs.conf /etc/nfs.conf.d/*.conf /etc/nfs.conf.local /etc/sysconfig/nfs
		log_cmd $OF 'nfsstat'
		timed_log_cmd $OF 'rpcinfo -p'

		log_cmd $OF "egrep '[[:space:]]nfs[[:space:]]|[[:space:]]nfs4[[:space:]]' /etc/fstab"
		IPADDRS=$(egrep '[[:space:]]nfs[[:space:]]|[[:space:]]nfs4[[:space:]]' /etc/fstab | egrep -v '^#|^;' | cut -d\: -f1 | sort | uniq)
		for IPADDR in $IPADDRS
		do
			ping_addr $OF 'NFS Server' $IPADDR
		done
		for IPADDR in $IPADDRS
		do
			log_cmd $OF "showmount -e $IPADDR"
		done
		NFS_FOUND=1
	fi

	if rpm -q nfs-kernel-server &> /dev/null
	then
		NFSSERVER='nfs-server.service'
		if rpm_verify $OF nfs-kernel-server
		then
			log_cmd $OF "systemctl status $NFSSERVER"
			log_cmd $OF 'exportfs -v'
			conf_files $OF /etc/exports
			if systemctl is-active --quiet $NFSSERVER
			then
				if timed_log_cmd $OF 'showmount'
				then
					log_cmd $OF 'showmount -e'
					log_cmd $OF 'showmount -a'
				fi
			fi
			NFS_FOUND=1
		fi
	fi

	(( $NFS_FOUND )) && echolog Done || echolog Skipped
}

ntp_info() {
	printlog "NTP..."
	(( $OPTION_NTP )) || { echolog Excluded; return 1; }
	OF=ntp.txt
	CONFFILE=/etc/ntp.conf
	addHeaderFile $OF
	if rpm -q chrony &> /dev/null
	then
	    if rpm_verify $OF chrony
		then
		    NTP_DAEMON=1
		    CONFFILE="/etc/chrony.conf"
		    log_cmd $OF "systemctl status chronyd.service"
		    FILES="$CONFFILE /etc/chrony.keys"
		    conf_files $OF $FILES
		    if log_cmd $OF "chronyc -n sources -v"
		    then
			    log_cmd $OF "chronyc -n sourcestats -v"
			    log_cmd $OF "chronyc -n tracking"
			    log_cmd $OF "chronyc activity"
		    else
			    NTP_DAEMON=0
		    fi
		    log_cmd $OF "timedatectl"
		    IPADDRS=$(egrep "^pool |^peer |^server " $CONFFILE | awk '{print $2}' | sort | uniq)
		    for IPADDR in $IPADDRS
		    do
			    ping_addr $OF 'NTP Server' $IPADDR
		    done
		    if [[ -f $CONFFILE ]]; then
			    log_write $OF "#___________________________________________________________#"
			    log_write $OF "#____[ Files Included in $CONFFILE ]____________________#"
			    log_write $OF
			    for KEYNAME in driftfile
			    do
				    FILES=$(grep ^${KEYNAME} $CONFFILE | awk '{print $2}')
				    conf_files $OF $FILES
			    done
			    KEYNAME=logdir
			    LOGDIR=$(grep ^${KEYNAME} $CONFFILE | awk '{print $2}')
			    [[ -z "$LOGDIR" ]] && LOGDIR='/var/log/chrony/'
			    FILES=$(find $LOGDIR -type f)
			    (( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
			    FILES="/var/log/messages"
			    (( $ADD_OPTION_LOGS )) && grep_log_files chrony $OF 0 $FILES || grep_log_files chrony $OF $VAR_OPTION_LINE_COUNT $FILES
		    fi
		    echolog Done
	    elif rpm -q ntp &> /dev/null
	    then
			CONFFILE=/etc/ntp.conf
			log_cmd $OF "systemctl status ntpd.service"
			log_cmd $OF 'ntpq -p'
			conf_files $OF $CONFFILE
			IPADDRS=$(egrep "^peer |^server " $CONFFILE | awk '{print $2}' | sort | uniq)
			for IPADDR in $IPADDRS
			do
				ping_addr $OF 'NTP Server' $IPADDR
			done
			if [[ -f $CONFFILE ]]; then
				log_write $OF "#___________________________________________________________#"
				log_write $OF "#____[ Files Included in $CONFFILE ]____________________#"
				log_write $OF
				for KEYNAME in driftfile
				do
					FILES=$(grep ^${KEYNAME} $CONFFILE | awk '{print $2}')
					conf_files $OF $FILES
				done
				KEYNAME=logfile
				FILES=$(grep ^${KEYNAME} $CONFFILE | awk '{print $2}')
				[[ -z "$FILES" ]] && FILES=/var/log/ntp
				test $ADD_OPTION_LOGS -gt 0 && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
			fi
			echolog Done
		else
			echolog Skipped
		fi
	fi
}

nvme_info() {
	printlog "NVMe..."
	(( $OPTION_NVME )) || { echolog Excluded; return 1; }
	OF=nvme.txt
	addHeaderFile $OF
	NVME_PKG='nvme-cli'
	STAS_PKG='nvme-stas'
	NVME_LOADED=0
	STAS_LOADED=0
	SKIP=0
	if rpm -q $NVME_PKG &>/dev/null; then
		rpm_verify $OF $NVME_PKG
		if lsmod | grep nvme &> /dev/null; then
			NVME_LOADED=1
		fi
		if (( $NVME_LOADED )); then
			log_cmd $OF "nvme list"
			log_cmd $OF "nvme list-subsys"
			log_cmd $OF "nvme discover"
			if (( $SLES_VER >= 155 )); then
				log_cmd $OF "nvme show-nbft -o json"
			elif (( $SLES_VER >= 154 )); then
				log_cmd $OF "nvme show-topology"
			fi
		fi

		FILES='/etc/nvme/discovery.conf /etc/nvme/config.json'
		if [[ -d /etc/nvme/ ]]; then
			TFILES=$(find /etc/nvme/ -type f | egrep -v "discovery.conf|config.json")
			[[ -n $TFILES ]] && FILES="${FILES} ${TFILES}"
		fi
		conf_files $OF $FILES
		if (( $NVME_LOADED )); then
			NVME_DEVICES=$(nvme list | grep /dev | awk '{print $1}')
			for NVME_DEVICE in $NVME_DEVICES
			do
				log_entry $OF note "Processing: $NVME_DEVICE"
				log_cmd $OF "nvme id-ctrl -H $NVME_DEVICE"
				log_cmd $OF "nvme fw-log $NVME_DEVICE"
				log_cmd $OF "nvme smart-log $NVME_DEVICE"
				log_entry $OF note "Done: $NVME_DEVICE"
				log_cmd $OF "smartctl --all $NVME_DEVICE"
				log_cmd $OF "nvme list-ns $NVME_DEVICE"
				log_cmd $OF "nvme list-ctrl $NVME_DEVICE"
				log_cmd $OF "nvme id-ns -H $NVME_DEVICE"
				log_cmd $OF "nvme error-log $NVME_DEVICE"
				log_cmd $OF "nvme show-regs $NVME_DEVICE"
			done
		fi
		log_cmd $OF "lspci -tv"
	else
		((SKIP++))
	fi
	if rpm -q $STAS_PKG &>/dev/null; then
		rpm_verify $OF $STAS_PKG
		log_cmd $OF 'systemctl status stacd.service'
		log_cmd $OF 'stacctl status'
		log_cmd $OF 'systemctl status stafd.service'
		log_cmd $OF 'stafctl status'
		FILES='/etc/stas/sys.conf /etc/stas/stacd.conf /etc/stas/stafd.conf'
		conf_files $OF $FILES
		log_cmd $OF 'journalctl -u stacd -o short-iso'
		log_cmd $OF 'journalctl -u stafd -o short-iso'
	else
		((SKIP++))
	fi

	(( $SKIP < 2 )) && echolog Done || echolog Skipped
}

udev_info() {
	printlog "UDEV..."
	(( $OPTION_UDEV )) || { echolog Excluded; return 1; }
	OF=udev.txt
	addHeaderFile $OF
	if rpm_verify $OF udev
	then
		UDEV_CONF=/etc/udev/udev.conf
		log_cmd $OF 'systemctl status systemd-udevd.service'
		log_cmd $OF 'systemctl status systemd-udev-trigger.service'
		conf_files $OF $UDEV_CONF
		log_cmd $OF "udevadm info -e"
		if [[ -f $UDEV_CONF ]]; then
			. $UDEV_CONF
			for UDEV_DIR in /lib/udev/rules.d /usr/lib/udev/rules.d ${udev_rules:=/etc/udev/rules.d}
			do
				if [[ -d $UDEV_DIR ]]; then
					FILES=$(find $UDEV_DIR/ -type f)
					conf_files $OF $FILES
				fi
			done
			[[ -n "$udev_db" ]] && log_cmd $OF "ls -l --time-style=long-iso ${udev_db}/"
		fi
		echolog Done
	else
		echolog Skipped
	fi
}

crash_info() {
	printlog "Crash Info..."
	# Call fslist_info first to search for core files
	(( $OPTION_CRASH )) || { echolog Excluded; return 1; }
	OF=crash.txt
	addHeaderFile $OF
	READ_KDUMP_CONFIG='/usr/lib/kdump/kdump-read-config.sh'
	SKIP=0
	rpm_verify $OF kdump
	rpm_verify $OF kexec-tools
	log_cmd $OF "uname -r"
	log_cmd $OF "systemctl status kdump.service"
	log_cmd $OF "kdumptool calibrate"
	(( SLES_VER < 156 )) && log_cmd $OF "kdumptool dump_config"
	conf_files $OF /proc/cmdline
	conf_files $OF /etc/sysconfig/kdump
	conf_files $OF /proc/sys/kernel/panic
	conf_files $OF /proc/sys/kernel/panic_on_oops
	conf_files $OF /sys/kernel/kexec_loaded
	conf_files $OF /sys/kernel/fadump/*
	conf_files $OF /sys/kernel/kexec_crash_loaded
	conf_files $OF /sys/kernel/kexec_crash_size
	conf_files $OF /etc/kdump.conf
	conf_files $OF /etc/udev/rules.d/*kexec.rules
	conf_files $OF /var/crash/*/vmcore-dmesg.txt
	conf_files $OF /var/crash/*/kexec-dmesg.log
	conf_files $OF /var/log/kdump.log
	log_cmd $OF "sysctl kernel.sysrq"
	log_cmd $OF 'sysctl kernel 2>/dev/null | grep panic'
	if rpm -q kdump &>/dev/null ; then
		if [[ -x $READ_KDUMP_CONFIG ]]; then
			. $READ_KDUMP_CONFIG
			DUMPDIR=${KDUMP_SAVEDIR#file://}
		else
			DUMPDIR=''
		fi
		if [[ -d $DUMPDIR ]]; then
			log_cmd $OF "find ${DUMPDIR}/"
		else
			log_entry $OF conf "KDUMP_SAVEDIR not found: ${DUMPDIR}"
		fi
	fi
	ANALYZEVMCORE_PREFIX=$ARCHIVE_PREFIX

	for i in $(ls -1 /var/log/${ANALYZEVMCORE_PREFIX}analyzevmcore* 2>/dev/null)
	do
		log_write $OF "#==[ Kernel Core Logs ]==========================#"
		log_write $OF "# $i"
		cat $i >> $LOG/$OF
		log_write $OF
	done

	# Application core dump information
	log_write $OF "#==[ Application Crash Info ]==========================#"
	log_write $OF
	log_icmd $OF "ulimit -c"
	log_cmd $OF "sysctl kernel.core_uses_pid"
	log_cmd $OF "sysctl kernel.core_pattern"
	conf_files $OF "/etc/sysconfig/ulimit /etc/security/limits.conf"
	if [[ -d /etc/security/limits.d/ ]]; then
		LIMITS_FILES=$(find /etc/security/limits.d/ -type f -name \*.conf)
		conf_files $OF $LIMITS_FILES
	fi

	if [[ -x /usr/bin/coredumpctl ]]; then
		log_cmd $OF "/usr/bin/coredumpctl list"
		if coredumpctl list 2>/dev/null | grep PID &>/dev/null; then
			PIDLIST=$(coredumpctl list | grep -v PID | awk '{print $5}')
			for COREPID in $PIDLIST
			do
				log_cmd $OF "coredumpctl info $COREPID"
			done
		fi
	fi
	CORE=$(cat /proc/sys/kernel/core_pattern 2>/dev/null)
	SEARCH_LIST=$(mktemp $LOG/crash.search.list.XXXXXXXX)
	COREFILE=""
	log_write $OF "#==[ Application Core Files ]==========================#"
	# Search core_pattern
	if [[ -d "$CORE" ]]; then
		log_write $OF "# Core Files Found in lsof-cwd, \$PATH, ld.so.conf: skipping invalid core_pattern: $CORE"
		COREDIR=''
		COREFILE='core'
	elif echo "$CORE" | grep '|' &>/dev/null; then
		log_write $OF "# Core Files Found in lsof-cwd, \$PATH, ld.so.conf: skipping piped core_pattern: $CORE"
		COREDIR=''
		COREFILE='core'
	elif echo "$CORE" | grep '/' &>/dev/null; then
		log_write $OF "# Core Files Found in $CORE, lsof-cwd, \$PATH, ld.so.conf"
		COREDIR=$(dirname "$CORE")
		COREFILE=$(basename "$CORE" | sed -e 's/\%./\*/g')
		ls -l --time-style=long-iso ${COREDIR}/${COREFILE} ${COREDIR}/${COREFILE}\.* ${COREDIR}/core ${COREDIR}/core\.* >> $SEARCH_LIST 2>/dev/null
	else
		log_write $OF '# Core File List in lsof-cwd, $PATH, ld.so.conf'
		COREFILE=$(echo $CORE | sed -e 's/\%./\*/g')
	fi

	# Search CWD per lsof
	if [[ -s ${LOG}/${LSOF_FILE} ]]; then
		SEARCH="$(cat ${LOG}/${LSOF_FILE} | grep '[[:space:]]cwd[[:space:]]' | awk '{print $9}' | sort | uniq)"
		for i in $SEARCH
		do
			ls -l --time-style=long-iso ${i}/${COREFILE} ${i}/${COREFILE}\.* ${i}/core ${i}/core\.* >> $SEARCH_LIST 2>/dev/null
		done
	fi
	# Search specific products
	SEARCH="/var/log/samba/cores/smbd/ /var/log/samba/cores/nmbd/"
	for i in $SEARCH
	do
		ls -l --time-style=long-iso ${i}/${COREFILE} ${i}/${COREFILE}\.* ${i}/core ${i}/core\.* >> $SEARCH_LIST 2>/dev/null
	done
	# Search $PATH
	SEARCH="$(echo $PATH | sed -e 's/:/ /g')"
	for i in $SEARCH
	do
		ls -l --time-style=long-iso ${i}/${COREFILE} ${i}/${COREFILE}\.* ${i}/core ${i}/core\.* >> $SEARCH_LIST 2>/dev/null
	done
	# Search ld.so.conf
	SEARCH="/lib /usr/lib /var/lib $(cat /etc/ld.so.conf | grep '^/')"
	for i in $SEARCH
	do
		ls -l --time-style=long-iso ${i}/${COREFILE} ${i}/${COREFILE}\.* ${i}/core ${i}/core\.* >> $SEARCH_LIST 2>/dev/null
	done
	# Search ld.so.conf includes
	LDINCLUDES=$(grep -i ^include /etc/ld.so.conf | awk '{print $2}')
	if [[ -n "$LDINCLUDES" ]]; then
		SEARCH=$(cat $LDINCLUDES 2>/dev/null)
		for i in $SEARCH
		do
			ls -l --time-style=long-iso ${i}/${COREFILE} ${i}/${COREFILE}\.* ${i}/core ${i}/core\.* >> $SEARCH_LIST 2>/dev/null
		done
	fi

	# include the core file list found
	cat $SEARCH_LIST | sort -k 9 | uniq | sed -e 's|//|/|g' > ${SEARCH_LIST}_U
	cat ${SEARCH_LIST}_U >> $LOG/$OF
	if [[ -s ${SEARCH_LIST}_U ]]; then
		FILES=$(cat ${SEARCH_LIST}_U | awk '{print $NF}')
	else
		FILES=""
	fi
	rm -f $SEARCH_LIST ${SEARCH_LIST}_U
	log_write $OF
	# determine the which app generated the core files found
	if [[ -n "$FILES" ]]; then
		log_cmd $OF "file $FILES"
	fi

	CHKBIN_PREFIX=$ARCHIVE_PREFIX

	for i in $(ls -1 /var/log/${CHKBIN_PREFIX}chkbin* 2>/dev/null)
	do
		log_write $OF "#==[ chkbin Logs ]==========================#"
		log_write $OF "# $i"
		cat $i >> $LOG/$OF
		log_write $OF
	done
	_sanitize_file $OF
	echolog Done
}

autofs_info() {
printlog "AUTOFS..."
	(( $OPTION_AUTOFS )) || { echolog Excluded; return 1; }
	OF=fs-autofs.txt
	addHeaderFile $OF
	if rpm_verify $OF autofs || rpm_verify $OF autofs4 || rpm_verify $OF autofs5
	then
		log_cmd $OF "systemctl status autofs.service"
		[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt" || log_cmd $OF "mount"
		log_cmd $OF 'ps aux | grep automount | grep -v grep'
		conf_files $OF /etc/sysconfig/autofs
		log_cmd $OF 'grep ^automount: /etc/nsswitch.conf'
		for SCHEME in $(grep ^automount: /etc/nsswitch.conf | sed -e 's/^.*:[ \t]*//')
		do
			log_write $OF "#--[ Automount Scheme: $SCHEME ]--#"
			case "$SCHEME" in
			files)
				if [[ -f /etc/auto.master ]]; then
					AFSMAPS=$(cat /etc/auto.master | grep -v ^# | awk '{print $2}' | cut -d\: -f2)
					FILES=''
					for MAP in $AFSMAPS
					do
						if [[ -e $MAP ]]; then
							FILES="$FILES $MAP"
						elif [[ -e /etc/$MAP ]]; then
							FILES="$FILES /etc/$MAP"
						else
							FILES="$FILES $MAP"
						fi
					done
					if [[ -d /etc/auto.master.d ]]; then
						MASTER_FILES=$(find /etc/auto.master.d/ -type f)
						FILES="$FILES $MASTER_FILES"
					fi
					conf_files $OF /etc/auto.master $FILES
				else
					log_write $OF "Missing /etc/auto.master"
					log_write $OF
				fi
				;;
			nis)
				if log_cmd $OF "ypcat -k auto.master"; then
					FILES=$(ypcat -k auto.master | grep -v ^# | awk '{print $2}' | cut -d\: -f2)
					for MAP in $FILES
					do
						log_cmd $OF "ypcat -k $MAP"
					done
				fi
				;;
			nisplus)
				log_cmd $OF "niscat -k auto_master.org_dir"
				;;
			ldap)
				conf_files $OF /etc/autofs_ldap_auth.conf
				log_cmd $OF "ldapsearch -x \"(&(objectclass=automountMap))\""
				log_cmd $OF "ldapsearch -x \"(&(objectclass=automount))\""
				log_cmd $OF "ldapsearch -x \"(&(objectclass=nisMap))\""
				log_cmd $OF "ldapsearch -x \"(&(objectclass=nisObject))\""
				;;
			esac
		done
		_sanitize_file $OF
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files automount $OF 0 $FILES || grep_log_files automount $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

rpm_full_verify() {
	OF=rpm-verify.txt
	OFTMP=$LOG/$RPM_QA_FILE
	if [[ $ADD_OPTION_RPMV -eq 1 ]]; then
		printlog -b "Full RPM Verification..."
		addHeaderFile $OF
		STARTCNT=1
		ENDCNT=$(cat $OFTMP | wc -l)
		for RPMNAME in $(cat $OFTMP)
		do
			if (( $VAR_OPTION_SBM )); then
				log_cmd $OF "rpm -V $RPMNAME"
			else
				printvrpmlog $RPMNAME "$((STARTCNT++)) of $ENDCNT"
				log_cmd $OF "rpm -V $RPMNAME"
			fi
			echolog Done
		done
		rm -f $OFTMP
	fi
}

apparmor_info() {
	printlog "AppArmor..."
	(( $OPTION_APPARMOR )) || { rm -f $AARPTMP &>/dev/null; echolog Excluded; return 1; }
	OF=security-apparmor.txt
	addHeaderFile $OF
	if rpm_verify $OF apparmor-parser
	then
		rpm_verify $OF apparmor-utils
		rpm_verify $OF apparmor-profiles
		[[ -f $AARPTMP ]] && cat $AARPTMP >> $LOG/$OF
		log_cmd $OF 'systemctl status apparmor.service'
		log_cmd $OF 'unconfined'
		log_cmd $OF 'aa-status'
		log_cmd $OF 'aa-notify -l'
		[[ -d /etc/apparmor ]] && FILES=$(find -L /etc/apparmor/ | grep '\.conf$') || FILES=""
		conf_files $OF $FILES
		log_files $OF 0 /var/log/audit/audit.log
		echolog Done
	else
		echolog Skipped
	fi

	rm -f $AARPTMP &>/dev/null
}

selinux_info() {
	printlog "SELinux..."
	(( $OPTION_SELINUX )) || { echolog Excluded; return 1; }
	OF=security-selinux.txt
	addHeaderFile $OF
	if rpm_verify $OF selinux-policy
	then
		for i in policycoreutils $(rpm -qa | grep selinux | grep -v "selinux-policy-[0-9]")
		do
			rpm_verify $OF "$i"
		done
		log_cmd $OF "zypper info selinux-policy"
		log_cmd $OF "selinux-ready"
		log_cmd $OF "sestatus"
		conf_files $OF '/proc/cmdline'
		for SERVICE in auditd restorecond
		do
			log_cmd $OF "systemctl status ${SERVICE}.service"
		done
		SEMANAGE_BIN=$(which semanage 2>/dev/null)
		if [[ -n $SEMANAGE_BIN ]]; then
			log_cmd $OF "sestatus -v"
			log_cmd $OF "$SEMANAGE_BIN boolean --list"
			log_cmd $OF "$SEMANAGE_BIN fcontext --list"
		else
			log_cmd $OF "sestatus -bv"
		fi
		log_cmd $OF "ps auxZww"
		if [[ -d /etc/selinux/ ]]; then
			ALL_FILES=$(find -L /etc/selinux/ -type f | sort)
			CFILES=$(grep "\.conf$" <<< "$ALL_FILES")
			NFILES=$(grep -v "\.conf$" <<< "$ALL_FILES")
			conf_text_files $OF $CFILES $NFILES
		fi
		log_cmd $OF "ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -i"
		echolog Done
	else
		echolog Skipped
	fi
}

ha_info() {
	printlog "HA Cluster..."
	(( $OPTION_HA )) || { echolog Excluded; return 1; }
	OF=ha.txt
	addHeaderFile $OF
	case $SLES_VER in
	15*|16*|999)
		if rpm_verify $OF pacemaker
		then
			log_cmd $OF "rpm -qa | egrep 'resource-agents|fence-agents|booth|cluster-glue|corosync|csync2|pacemaker|crmsh|libqb|hawk|dlm|lvm2|cluster-md|ocfs2|gfs2|drbd'"
			log_cmd $OF "systemctl status pacemaker.service"
			CONF_FILES="/etc/corosync/corosync.conf /etc/sysconfig/ctdb /etc/sysconfig/sbd"
			if [[ -s /etc/xinetd.d/csync2 ]]; then
				TMPORT=$(grep -i port /etc/xinetd.d/csync2 | awk '{print $3}')
				log_cmd $OF "ss -nlp | grep $TMPORT"
			fi
			log_cmd $OF 'chronyc sources -v'
			log_cmd $OF 'crm_mon -r -1'
			log_cmd $OF 'crm_mon -r -n -1'
			# Display node attributes ; Nov 15, 2018 ; Added by Ahmad Al Zayed
			log_cmd $OF 'crm_mon -A -1' 
			log_cmd $OF 'corosync-cfgtool -s'
			# More corosync information ; Dec 6, 2018 ; Added by Ahmad Al Zayed
			log_cmd $OF 'crm corosync status' 
			log_cmd $OF 'crm configure show'
			conf_files $OF $CONF_FILES
			if [[ -s /etc/sysconfig/sbd ]]; then
				. /etc/sysconfig/sbd
				for SBD in $(echo $SBD_DEVICE | sed -e 's/;/ /g')
				do
					if timed_log_cmd $OF "sbd -d $SBD list"; then
						log_cmd $OF "sbd -d $SBD dump"
					fi
				done
			fi
			log_cmd $OF 'ls -lR --time-style=long-iso /etc/csync2'
			conf_files $OF /etc/csync2/csync2.cfg /etc/xinetd.d/csync2
			CURRENT_PATH=$(pwd)
			cd $LOG
			for HBRDIR in $VAR_OPTION_HBREPORT_DIRS
			do
				HBRS=$(find $HBRDIR -maxdepth 1 -type f -mtime -30 2>/dev/null | egrep "/(hb|crm)[_-]?report[0-9a-zA-Z._-]*\.tar\.(bz2|gz)$")
				if [[ -n "$HBRS" ]]; then
					for HBR_PATH in $HBRS
					do
						HBR=$(basename $HBR_PATH)
						log_cmd $OF "tar jxf ${HBR_PATH}"
						conf_files $OF "$LOG/${HBR%%.tar.bz2}/analysis.txt"
					done
				fi
			done
			cd $CURRENT_PATH
			CURRENT_CIB=''
			FILES=''
			if [[ -d /var/lib/heartbeat/ ]]; then
				FILES=$(find /var/lib/heartbeat/ -type f | egrep -v "cores|pengine|trace_ra|hb_uuid|cib\.xml")
				[[ -e /var/lib/heartbeat/crm/cib.xml ]] && CURRENT_CIB='/var/lib/heartbeat/crm/cib.xml'
				for i in $(find /var/lib/heartbeat/cores -type f)
				do
					log_cmd $OF "file $i"
				done
			fi
			if [[ -d /var/lib/pacemaker/ ]]; then
				TFILES=$(find /var/lib/pacemaker/ -type f | egrep -v "blackbox|cores|pengine|hb_uuid|cib\.xml")
				FILES="$FILES $TFILES"
				[[ -e /var/lib/pacemaker/cib/cib.xml ]] && CURRENT_CIB='/var/lib/pacemaker/cib/cib.xml'
			fi
			log_cmd $OF 'cibadmin -Q'
			conf_files $OF $CURRENT_CIB $FILES
			FILES="/var/log/ha-log /var/log/pacemaker/pacemaker.log /var/log/ctdb/log.ctdb"
			(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
			CORBIN="/usr/sbin/corosync-fplay"
			if [[ -x $CORBIN ]]; then
				CLN=$($CORBIN 2>/dev/null | wc -l)
				if [[ $CLN -gt 1000 ]]; then
					log_cmd $OF 'corosync-fplay | head -500'
					log_cmd $OF 'corosync-fplay | tail -500'
				else
					log_cmd $OF 'corosync-fplay'
				fi
			fi
			conf_files $OF /etc/hawk/server.json /etc/sysconfig/hawk
			CERT="$(grep -Po '^HAWK_CERT\s*=\s*"\s*\K(/[^"]+)(?=.*)' /etc/sysconfig/hawk)"
			if [[ -n $CERT ]]; then
				log_cmd $OF "openssl x509 -in $CERT -subject -startdate -enddate -noout -ext subjectAltName"
			fi
			log_cmd $OF 'systemctl status hawk-backend.service'
			log_cmd $OF 'systemctl status hawk.service'

			echolog Done
		else
			echolog Skipped
		fi
		;;
	*) echolog Skipped ;;
	esac
}

slp_info() {
	printlog "SLP..."
	(( $OPTION_SLP )) || { echolog Excluded; return 1; }
	OF=slp.txt
	addHeaderFile $OF
	if rpm_verify $OF openslp-server
	then
		log_cmd $OF "systemctl status slpd.service"
	fi
	if rpm_verify $OF openslp
	then
		conf_files $OF /etc/slp.conf
		if [[ -s /etc/slp.conf ]]; then
			IPADDRS=$(grep -i '^net.slp.DAAddresses' /etc/slp.conf | sed -e "s/[[:space:]]+//g;s/\'//g;s/\"//g" | cut -d= -f2 | sed -e "s/,/ /g")
			for IPADDR in $IPADDRS
			do
				ping_addr $OF 'SLP DA' $IPADDR
			done
		fi
		conf_files $OF /etc/slp.reg /etc/slp.spi
		if [[ -d /etc/slp.reg.d ]]; then
			FILES=$(find -L /etc/slp.reg.d/ -type f)
			conf_files $OF $FILES
		fi
		log_cmd $OF 'slptool findscopes'
		if (( $ADD_OPTION_SLP )); then
			echonlog "Please Wait..."
			if log_cmd $OF 'slptool findsrvtypes'
			then
				echonlog Services
				STATE=0
				SRV_TYPES=''
				while read LINE
				do
					if (( $STATE )); then
						SRV_TYPES="$SRV_TYPES $LINE"
					elif echo $LINE | grep findsrvtypes &>/dev/null; then
						STATE=1
					fi
				done < ${LOG}/${OF}
				for SERVICE in $SRV_TYPES
				do
					log_cmd $OF "slptool findsrvs $SERVICE"
				done
			fi
		else
			log_write $OF "ERROR: Unable to get full SLP service lists, check 'slptool findsrvtypes'"
		fi
	fi
	echolog Done
	FILES="/var/log/slpd.log"
	(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
}

ocfs2_info() {
	printlog "OCFS2..."
	(( $OPTION_OCFS2 )) || { echolog Excluded; return 1; }
	OF=ocfs2.txt
	OCFS2_MODULES=0
	addHeaderFile $OF
	if rpm_verify $OF ocfs2-tools
	then
		if lsmod | grep ocfs2_stack_user[[:space:]] &>/dev/null && lsmod | grep ocfs2[[:space:]] &>/dev/null
		then
			OCFS2_MODULES=1
		fi
		[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt" || log_cmd $OF "mount"
		(( OCFS2_MODULES )) && timed_log_cmd $OF "mounted.ocfs2 -d"
		(( OCFS2_MODULES )) && timed_log_cmd $OF "mounted.ocfs2 -f"
		log_cmd $OF "ps aux | grep ocfs2 | grep -v grep"
		log_cmd $OF "lsmod | grep ocfs2"
		CHECKDIR="/sys/o2cb"
		if [[ -d $CHECKDIR ]]; then
			FILES=$(find ${CHECKDIR}/ -type f)
			conf_files $OF $FILES
		fi
		CHECKDIR="/sys/kernel/config/cluster"
		if [[ -d $CHECKDIR ]]; then
			FILES=$(find ${CHECKDIR}/ -type f)
			conf_files $OF $FILES
		fi
		(( OCFS2_MODULES )) && DEVICES=$(/sbin/mounted.ocfs2 -d | grep ^/ | awk '{ print $1}') || DEVICES=''
		log_entry $OF x "OCFS2 Devices"
		log_write $OF $DEVICES
		log_write $OF
		if [[ -n "$DEVICES" ]]; then
			O2C=$(mktemp $LOG/ocfs2_commands.XXXXXXXX)
			for DEVICE in $DEVICES
			do
				log_entry $OF note "OCFS2 Superblock Info on Device $DEVICE"
				echo 'stats' > $O2C
				wait_trace_on "debugfs.ocfs2 -n -f $O2C $DEVICE"
				SLOTS=$(debugfs.ocfs2 -n -f $O2C $DEVICE | awk '/Max Node Slots:/ { print $4 }')
				wait_trace_off
				for CMD in 'stats' 'stat //global_bitmap' 'slotmap' 'stat //slot_map' 'stat //heartbeat'
				do
					echo $CMD > $O2C
					wait_trace_on "debugfs.ocfs2 -n -R \"$CMD\" $DEVICE"
					log_entry $OF command "debugfs.ocfs2 -n -R \"$CMD\" $DEVICE"
					debugfs.ocfs2 -n -f $O2C $DEVICE >> $LOG/$OF 2>&1
					log_write $OF
					wait_trace_off
				done
				log_entry $OF note "SLOT Details for $SLOTS Slots on $DEVICE"
				for SLOT in $(seq --format="%04g" 0 $[${SLOTS}-1])
				do
					for CMDEL in inode_alloc extent_alloc local_alloc truncate_log journal orphan_dir
					do
						CMD="stat //${CMDEL}:${SLOT}"
						wait_trace_on "debugfs.ocfs2 -n -R \"$CMD\" $DEVICE"
						echo $CMD > $O2C
						log_entry $OF command "debugfs.ocfs2 -n -R \"$CMD\" $DEVICE"
						debugfs.ocfs2 -n -f $O2C $DEVICE >> $LOG/$OF 2>&1
						log_write $OF
						wait_trace_off
					done
				done
			done
			rm -f $O2C
		fi
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files ocfs $OF 0 $FILES || grep_log_files ocfs $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

gfs2_info() {
	printlog "GFS2..."
	(( $OPTION_GFS2 )) || { echolog Excluded; return 1; }
	OF=fs-gfs2.txt
	GFS2_MODULES=0
	addHeaderFile $OF
	if rpm_verify $OF gfs2-utils
	then
		if  lsmod | grep gfs2[[:space:]] &>/dev/null
		then
			GFS2_MODULES=1
		fi
		log_cmd $OF "rpm -qa | egrep 'gfs2-utils|gfs2-kmp-default'"
		[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt --types gfs2" || log_cmd $OF "mount --types gfs2"
		log_cmd $OF "ps aux | grep gfs2 | grep -v grep"
		log_cmd $OF "lsmod | grep gfs2"
		(( GFS2_MODULES )) && DEVICES=$(find /sys/fs/gfs2/ -name device -and -type l -exec sh -c 'readlink -ev {} | sed  "s/.*\//\/dev\//g" ' \;) || DEVICES=''
		log_entry $OF x "GFS2 Devices"
		log_write $OF "$DEVICES"
		log_write $OF

		for DEVICE in $DEVICES
		do
		    GFS2_EDIT_OPTS="sb root master jindex per_node inum statfs quota"
		    log_cmd $OF "gfs2_edit -p $GFS2_EDIT_OPTS $DEVICE"
		    log_write $OF
		done
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files gfs2 $OF 0 $FILES || grep_log_files gfs2 $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

drbd_info() {
	printlog "DRBD..."
	(( $OPTION_DRBD )) || { echolog Excluded; return 1; }
	OF=drbd.txt
	addHeaderFile $OF
	if [[ -s /etc/drbd.conf ]]
	then
		rpm_verify $OF drbd
		log_cmd $OF 'systemctl status drbd.service'
		log_cmd $OF "egrep \"drbd\" $RPMPATH"
		log_write $OF
		log_cmd $OF "lsmod | grep drbd"
		log_cmd $OF "modinfo drbd"
		log_cmd $OF "drbd-overview" 
		# Added By Ahmad Al Zayed - Feb 21, 2019 to get few drbd output & configuration 
		log_cmd $OF "drbdadm status" 
		log_cmd $OF "drbdadm dump"
		log_cmd $OF "cat /proc/drbd"
		log_cmd $OF "ps aux | grep drbd | grep -v grep"
		[[ -x /usr/bin/findmnt ]] && log_cmd $OF "findmnt" || log_cmd $OF "mount"
		(( $IO_DELAYS )) || log_cmd $OF "df -Th"
		if [[ -s /etc/drbd.conf ]]; then
			DIRLIST=$(cat /etc/drbd.conf | grep ^include | cut -d\" -f2 | sed 's!\(.*\)/.*!\1/!' | sort | uniq)
			FILES=''
			for DIR in $DIRLIST
			do
				# We need to add "/etc/" since $DIR will have dir inside /etc/ 
				# However this find will find all files inside a specific folder It's okay
				# Will end up with /etc/drbd.conf/nfs.res nfs.RES nfs.stop .... 
				[[ -d "/etc/$DIR" ]] && FILES="$FILES $(find -L "/etc/$DIR" -type f)"
				[[ -d $DIR ]] && FILES="$FILES $(find -L $DIR -type f)"
			done
			conf_files $OF "/etc/drbd.conf $FILES"
		fi
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files drbd $OF 0 $FILES || grep_log_files drbd $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

haproxy_info() {
	printlog "HAPROXY..."
	(( $OPTION_HAPROXY )) || { echolog Excluded; return 1; }
	OF=haproxy.txt
	addHeaderFile $OF
	if [[ -s /etc/haproxy/haproxy.cfg ]]
	then
		rpm_verify $OF haproxy
		log_cmd $OF 'systemctl status haproxy.service'
		log_cmd $OF "egrep \"haproxy\" $RPMPATH"
		log_write $OF
		log_cmd $OF "ps aux | grep haproxy | grep -v grep"
		conf_files $OF "/etc/haproxy/haproxy.cfg"
		FILES="/var/log/messages"
		(( $ADD_OPTION_LOGS )) && grep_log_files haproxy $OF 0 $FILES || grep_log_files haproxy $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

root_shell_history_info() {
	printlog "Command History..."
	(( $OPTION_HISTORY )) || { echolog Excluded; return 1; }
	OF=shell_history.txt
	addHeaderFile $OF
	log_icmd $OF "history"
	conf_files $OF /root/.bash_history
	echolog Done
}

memory_info() {
	printlog "Memory Details..."
	(( $OPTION_MEM )) || { echolog Excluded; return 1; }
	OF=memory.txt
	addHeaderFile $OF
	log_cmd $OF "vmstat 1 4"
	log_cmd $OF "free -k"
	conf_files $OF /proc/meminfo /proc/vmstat
	log_cmd $OF 'sysctl -a 2>/dev/null | grep ^vm'
	[[ -d /sys/kernel/mm/transparent_hugepage/ ]] && FILES=$(find /sys/kernel/mm/transparent_hugepage/ -type f) || FILES=''
	conf_files $OF /proc/buddyinfo /proc/slabinfo /proc/zoneinfo $FILES
	if rpm -q numactl &>/dev/null; then
		log_cmd $OF 'numactl --hardware'
		log_cmd $OF 'numastat'
	fi
	if [[ -e /sys/kernel/debug/vmmemctl ]]; then
		conf_files $OF /sys/kernel/debug/vmmemctl
	fi
	if (( EXT_SCALING_DISABLED )); then
		if [[ -x /usr/bin/pmap ]]; then
			for I in $(ps axo pid)
			do
				log_cmd $OF "pmap $I"
			done
		fi
	fi
	echolog Done
}

open_files() {
	printlog "Open Files..."
	(( $OPTION_OFILES )) || { echolog Excluded; return 1; }
	OF=${LSOF_FILE}
	addHeaderFile $OF
	if rpm_verify $OF lsof
	then
		log_cmd $OF "lsof -b -n -l +fg -P -Ki 2>/dev/null"
		echolog Done
	else
		echolog Skipped
	fi
}

samba_info() {
	printlog "Samba..."
	(( $OPTION_SMB )) || { echolog Excluded; return 1; }
	OF=samba.txt
	RPMPATH=$LOG/$RPMFILE
	addHeaderFile $OF

	log_cmd $OF "egrep \"samba|smb|cifs|libtallo|libtdb|libwbclient\" $RPMPATH"
	log_write $OF

	if rpm_verify $OF samba
	then
		for SERVICE in smb nmb
		do
			log_cmd $OF "systemctl status ${SERVICE}.service"
		done
		SAMBA_LIB="/var/lib/samba"
		SAMBA_KRB="$SAMBA_LIB/smb_krb5"
		if [[ -d $SAMBA_LIB ]]; then
			log_cmd $OF "ls -al $SAMBA_LIB"
			conf_files $OF $SAMBA_LIB/browse.dat $SAMBA_LIB/wins.dat
		fi
		if [[ -d $SAMBA_KRB ]]; then
			conf_files $OF /etc/krb5.conf ${SAMBA_KRB}/* 
		fi
	fi

	if rpm_verify $OF samba-client
	then
		conf_files $OF /etc/samba/smb.conf
		log_cmd $OF "testparm -sv"
		log_cmd $OF "pdbedit -L"
	fi

	if rpm_verify $OF samba-winbind
	then
		for SERVICE in winbind
		do
			log_cmd $OF "systemctl status ${SERVICE}.service"
		done
		log_cmd $OF 'wbinfo -u'
		log_cmd $OF 'wbinfo -g'
		log_cmd $OF 'wbinfo -p'
		log_cmd $OF 'wbinfo --own-domain'
		log_cmd $OF 'wbinfo --trusted-domains'
		log_cmd $OF 'wbinfo --check-secret'
		conf_files $OF /etc/samba/lmhosts /etc/nsswitch.conf /etc/security/pam_winbind.conf
	fi

	if [[ -d /var/log/samba ]]; then
		FILES=$(find /var/log/samba/ -type f | grep -v '/core')
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	fi
	
	echolog Done
}

fslist_info() {
	printlog "Filesystem List..."
	(( $ADD_OPTION_FSLIST )) || { echolog Skipped; return 1; }
	OF=$FSLIST_FILE
	addHeaderFile $OF
	timed_log_cmd $OF 'find / -path /.snapshots -prune -o -print'
	echolog Done
}

fslist_ufiles_info() {
	printlog "Additional Files List..."
	(( $OPTION_UFILES )) || { echolog Skipped; return 1; }
	OF=fs-files-additional.txt
	addHeaderFile $OF
	UFUID=$(stat -c%u $FSLIST_ADD_FILE)
	conf_files $OF $FSLIST_ADD_FILE
	if [[ "$UFUID" = "0" ]]; then
		while read FILE
		do
			if [[ -d "$FILE" ]]; then
				log_write $OF "#==[ Directory ]====================================#"
				log_write $OF "# $FILE - Not a regular file"
				log_write $OF
			elif [[ -e "$FILE" ]]; then
				MIME1=$(file -Li "$FILE" | awk -F\: '{print $2}' | awk '{print $1}' | cut -d/ -f1)
				MIME2=$(file -Li "$FILE" | awk -F\: '{print $2}' | awk '{print $1}' | cut -d/ -f2)
				case $MIME1 in
				text) FILE=${FILE// /%7B%20%7D%7B%20%7D}; log_files $OF 0 "$FILE" ;;
				application)
					case $MIME2 in
					x-shellscript) FILE=${FILE// /%7B%20%7D%7B%20%7D}; log_files $OF 0 "$FILE" ;;
					x-perl) FILE=${FILE// /%7B%20%7D%7B%20%7D}; log_files $OF 0 "$FILE" ;;
					*) BFILE=$(basename "$FILE"); log_cmd $OF "uuencode -m \"$FILE\" \"$BFILE\"" ;;
					esac
					;;
				*) BFILE=$(basename "$FILE"); log_cmd $OF "uuencode -m \"$FILE\" \"$BFILE\"" ;;
				esac
			else
				FILE=${FILE// /%7B%20%7D%7B%20%7D}; log_files $OF 0 "$FILE"
			fi
		done < $FSLIST_ADD_FILE
		echolog Done
	else
		echolog Error
		log_write $OF "ERROR: Invalid owner for ${FSLIST_ADD_FILE}, must be owned by root"
	fi
}

smartmon_info() {
	printlog "SMART Disks..."
	(( $OPTION_SMART )) || { echolog Excluded; return 1; }
	OF=fs-smartmon.txt
	addHeaderFile $OF
	if rpm_verify $OF smartmontools
	then
		SMART_FOUND=0
		log_cmd $OF 'systemctl status smartd.service'
		conf_files $OF /proc/partitions /etc/smartd.conf
		for DISK in $(cat /proc/partitions | grep -v ^m | grep -v ^$ | awk '{print $4}')
		do
			case $DISK in
			sd[a-z]|sd[a-z][a-z]) log_cmd smartmon-$DISK "smartctl --all /dev/$DISK"; SMART_FOUND=1 ;;
			hd[a-z]|hd[a-z][a-z]) log_cmd smartmon-$DISK "smartctl --all /dev/$DISK"; SMART_FOUND=1 ;;
			esac
		done
		if (( SMART_FOUND )); then
			log_write $OF "#==[ Quick Status Check ]===========================#"
			grep -i "^SMART overall" $LOG/smartmon-* | awk -F/ '{print $5}' >> $LOG/$OF
			log_write $OF 
			cat $LOG/smartmon-* >> $LOG/$OF
			rm -f $LOG/smartmon-*
		fi
		echolog Done
	else
		echolog Skipped
	fi
}

ldap_info() {
	printlog "LDAP..."
	(( $OPTION_LDAP )) || { echolog Excluded; return 1; }
	OF=ldap.txt
	addHeaderFile $OF
	SKIP=0

	log_write $OF "#___________________________________________________________#"
	log_write $OF "#____[ LDAP Client Information ]____________________________#"
	log_write $OF
	if rpm_verify $OF pwdutils
	then
		conf_files $OF /etc/ldap.conf
		IPADDRS=$(grep -i '^uri[[:space:]]' /etc/ldap.conf | sed -e 's!uri[[:space:]]*!!g;s!ldap://!!g;s!ldaps://!!g;s!ldapi://[[:alnum:][:punct:]]*!!g')
		for I in $IPADDRS
		do
			IPADDR=$(echo $I | sed -e "s/:[[:digit:]]*//g")
			ping_addr $OF 'LDAP Server' $IPADDR
		done
		conf_files $OF /etc/nsswitch.conf /etc/sysconfig/ldap
	else
		((SKIP++))
	fi

	# Right now only openLDAP v2 is supported
	if rpm_verify $OF openldap2-client
	then
		LDAP_BIN="/usr/bin/ldapsearch"
		LDAP_CONF="/etc/openldap/ldap.conf"
		conf_files $OF $LDAP_CONF
		if [[ -s $LDAP_CONF ]]; then
			IPADDRS=$(grep -Pio '^uri\s+ldaps?://\K(.*)' $LDAP_CONF)
			for I in $IPADDRS
			do
				IPADDR=$(echo $I | sed -e "s/:[[:digit:]]*//g")
				ping_addr $OF 'LDAP Server' $IPADDR
			done
		fi
		log_write $OF "#==[ Search for LDAP Server's root DSE ]============#"
		if log_cmd $OF "$LDAP_BIN -x -b \"\" -s base \"objectclass=*\""; then
			log_write $OF "LDAP Connection: Success"
		else
			log_write $OF "LDAP Connection: FAILED"
		fi
		log_write $OF
	else
		((SKIP++))
	fi

	# Right now only openLDAP v2 is supported
	log_write $OF "#___________________________________________________________#"
	log_write $OF "#____[ LDAP Server Information ]____________________________#"
	log_write $OF
	if rpm_verify $OF openldap2 || rpm_verify $OF openldap2_5
	then
		SLAPD_CONF_BACKEND=$(grep -Po \
			'^OPENLDAP_CONFIG_BACKEND\s*=\s*"*\K([^"\s$]+)(?=.*)' \
			/etc/sysconfig/openldap)
		SLAPD_CONF=/etc/openldap/slapd.conf
		SLAPD_DIR=/var/lib/ldap
		if [[ "$SLAPD_CONF_BACKEND" == "files" ]] && [[ -f $SLAPD_CONF ]]
		then
			SLAPD_DIR=$(grep -i ^directory $SLAPD_CONF | awk '{print $2}')
			SLAPD_PIDF=$(grep -i ^pidfile $SLAPD_CONF | awk '{print $2}')
			[[ -z "$SLAPD_PIDF" ]] && SLAPD_PIDF="/var/run/slapd/slapd.pid"
			if [[ -f $SLAPD_PIDF ]]; then
				SLAPD_PID=$(cat $SLAPD_PIDF)
			else
				SLAPD_PID=""
			fi
			# schema files collection makes sense only in 'file' conf backend
			log_cmd $OF "ls -al /etc/openldap/schema"
			SLAPD_SCHEMAS=$(grep ^include $SLAPD_CONF | awk '{print $2}')
			if [[ -n "$SLAPD_SCHEMAS" ]]
			then
				log_write $OF "#___________________________________________________________#"
				log_write $OF "#____[ Schema Files Included in LDAP Server ]_______________#"
				log_write $OF
				log_write $OF "$SLAPD_SCHEMAS"
				log_write $OF
				conf_files $OF $SLAPD_SCHEMAS
			fi
		elif [[ "$SLAPD_CONF_BACKEND" == "ldap" ]]
		then
			SLAPD_CONF= # useless in 'ldap' config backend
			SLAPD_DIR=$(grep -IRhPo '^olcDbDirectory: \K(.*)' /etc/openldap/slapd.d/)
			SLAPD_PIDF=$(grep -Po '^olcPidFile: \K(.*)' /etc/openldap/slapd.d/cn=config.ldif)
			if [[ -f $SLAPD_PIDF ]]
			then
				SLAPD_PID=$(cat $SLAPD_PIDF)
			else
				SLAPD_PID=""
			fi
			FILES=$(find /etc/openldap/slapd.d/ -type f)
		fi
		log_cmd $OF 'systemctl status ldap.service'
		log_cmd $OF 'systemctl status slapd.service'
		log_cmd $OF "ss -nlp | grep slapd"

		conf_files $OF $SLAPD_CONF /etc/sysconfig/openldap $FILES

		# there can be multiple databases!
		for dir in $SLAPD_DIR; do
			conf_files $OF $dir/DB_CONFIG
			log_cmd $OF "ls -al $dir"
		done

		if [[ -n "$SLAPD_PID" ]]
		then
			log_cmd $OF "lsof -b +M -n -l +fg -P -p ${SLAPD_PID}"
		fi
		_sanitize_file $OF
	else
		((SKIP++))
	fi

	(( $SKIP < 3 )) && echolog Done || echolog Skipped
}

etc_info() {
	printlog "ETC..."
	(( $OPTION_ETC )) || { echolog Excluded; return 1; }
	OF=etc.txt
	addHeaderFile $OF
	# Let us get alternatives output
	log_cmd $OF "update-alternatives --get-selections"
	conf_files $OF $(find -L /etc/ -type f | egrep "(conf|cfg|nfs.conf.local)$" | egrep -v "rhn/rhn.conf$")
	[[ -d /etc/logrotate.d ]] && conf_files $OF /etc/logrotate.d/*
	conf_files $OF /etc/rc.dialout /etc/ppp/options /etc/ppp/ioptions /etc/ppp/peers/pppoe /etc/motd
	_sanitize_file $OF
	echolog Done
}

sysconfig_info() {
	printlog "SYSCONFIG..."
	(( $OPTION_SYSCONFIG )) || { echolog Excluded; return 1; }
	OF=sysconfig.txt
	addHeaderFile $OF
	for FILE in $(find /etc/sysconfig/ -maxdepth 1 -type f | sort -f)
	do
		conf_files $OF $FILE
	done
	for FDIR in $(find /etc/sysconfig/ -maxdepth 1 -type d | grep -v "/etc/sysconfig/$" | sort)
	do
		for FILE in $(find -L ${FDIR}/ -type f | sort)
		do
			conf_files $OF $FILE
		done
	done
	_sanitize_file $OF
	echolog Done
}

proc_info() {
	printlog "PROC..."
	(( $OPTION_PROC )) || { echolog Excluded; return 1; }
	OF=proc.txt
	addHeaderFile $OF

	conf_files $OF $PROC_FILES
	for PROCDIR in $PROC_DIRS_DEPTH_ONE
	do
		FILES=$(find $PROCDIR -maxdepth 1 -type f 2>/dev/null | egrep -iv "${PROC_DIRS_DEPTH_ONE_FILTER_OUT}" | sort -f)
		conf_files $OF $FILES
	done
	(( EXT_SCALING_DISABLED )) && PROC_DIRS_DEPTH_FULL="/proc/irq/ /proc/sys/" || PROC_DIRS_DEPTH_FULL="/proc/sys/"

	for PROCDIR in $PROC_DIRS_DEPTH_FULL
	do
		FILES=$(find $PROCDIR -type f 2>/dev/null | egrep -iv "${PROC_DIRS_DEPTH_FULL_FILTER_OUT}" | sort -f)
		conf_files $OF $FILES
	done

	if (( EXT_SCALING_DISABLED )); then
		if (( SLES_VER >= 150 && ${INCLUDE_NETWORK_NAMESPACES} )); then
			# Check process name space against the default name space
			log_write $OF "#==[ Processes with a Different Default Name Space ]==#"
			log_write $OF "# name_space : process_id : command"
			NS_IPC_DEFAULT="$(readlink /proc/1/ns/ipc | sed 's/\[/\\[/;s/\]/\\]/')"
			NS_NET_DEFAULT="$(readlink /proc/1/ns/net | sed 's/\[/\\[/;s/\]/\\]/')"
			NS_PID_DEFAULT="$(readlink /proc/1/ns/pid | sed 's/\[/\\[/;s/\]/\\]/')"
			NS_UTS_DEFAULT="$(readlink /proc/1/ns/uts | sed 's/\[/\\[/;s/\]/\\]/')"
			for PID_PATH in /proc/[0-9]*
			do
				wait_trace_on "Compare $PID_PATH name space with the default"
				if [[ -e ${PID_PATH} ]]
				then
					CMD_LINE=$(cat ${PID_PATH}/cmdline 2>/dev/null | tr '\0' ' ')
					STATE=$(sed -n 's/^State:[[:blank:]]\+\([^[:blank:]]\)[[:blank:]]\+.*/\1/p' 2>/dev/null < ${PID_PATH}/status)
					PID=$(basename $PID_PATH)
					NS_IPC="$(readlink ${PID_PATH}/ns/ipc 2>/dev/null | sed 's/\[/\\[/;s/\]/\\]/')"
					NS_NET="$(readlink ${PID_PATH}/ns/net 2>/dev/null | sed 's/\[/\\[/;s/\]/\\]/')"
					NS_PID="$(readlink ${PID_PATH}/ns/pid 2>/dev/null | sed 's/\[/\\[/;s/\]/\\]/')"
					NS_UTS="$(readlink ${PID_PATH}/ns/uts 2>/dev/null | sed 's/\[/\\[/;s/\]/\\]/')"
					if [[ "$STATE" != "Z" || "$STATE" != "D" ]]
					then
						if [[ -n "$CMD_LINE" ]]
						then
							[[ "$NS_IPC_DEFAULT" != "$NS_IPC" ]] && log_write $OF "ipc : $PID : $CMD_LINE"
							[[ "$NS_NET_DEFAULT" != "$NS_NET" ]] && log_write $OF "net : $PID : $CMD_LINE"
							[[ "$NS_PID_DEFAULT" != "$NS_PID" ]] && log_write $OF "pid : $PID : $CMD_LINE"
							[[ "$NS_UTS_DEFAULT" != "$NS_UTS" ]] && log_write $OF "uts : $PID : $CMD_LINE"
						fi
					fi
				fi
				wait_trace_off
			done
			log_write $OF
			log_write $OF "#==[ Processes Mapped to RPM Package ]==#"
			log_write $OF "# process_id -> binary -> RPM package that owns the binary"
			for PID in /proc/[0-9]*
			do
        			PID=${PID##*/}
        			if [[ -d "/proc/${PID}" ]]; then
                			BINARY=$(readlink -e "/proc/${PID}/exe" 2>/dev/null)
                			if [[ -n $BINARY ]]; then
                       		 		PACKAGE=$(rpm -qf $BINARY)
                        			log_write $OF "PID ${PID} -> $BINARY -> $PACKAGE"
                			fi
        			fi
			done
			log_write $OF
		fi
	fi

	# only include cpu0 sched_domain information, all others are excluded
	SCHED_DOMAIN='/proc/sys/kernel/sched_domain/cpu0'
	if [[ -d ${SCHED_DOMAIN} ]]; then
		FILES=$(find ${SCHED_DOMAIN} -type f 2>/dev/null | sort -f)
		conf_files $OF $FILES
	fi
	# cpuset information relates to processes
	log_cmd $OF "grep cpuset /etc/mtab"
	CPUSET=$(grep -m 1 -E ' cpuset |cgroup .*cpuset' /etc/mtab | cut -d' ' -f2)
	if [[ -n "$CPUSET" ]]; then
		log_cmd $OF "find -L ${CPUSET}/ -type f"
		FILES=$(find -L ${CPUSET}/ -type f)
		conf_files $OF $FILES
	fi
	echolog Done
}

drm_sub_info() {
	log_cmd $OF 'systool -vc drm'
	log_cmd $OF 'ls -lR --time-style=long-iso /sys/class/drm'
	log_cmd $OF 'modetest'
	log_cmd $OF 'intel_reg_dumper'
	for i in /sys/class/drm/card?/device/uevent
	do
		module=$(cat $i | grep DRIVER | cut -d= -f2)
		log_cmd $OF "modeprint $module"
	done
	for i in /sys/class/drm/card*-*
	do
		log_cmd $OF "cat $i/status $i/enabled "
		log_cmd $OF 'hexdump -e '"'16/1 "'"%2.2x ""  "'"' -e '16/1 "'"%_p""\n"'"' $i/edid"
	done
	log_cmd $OF 'dmesg -T | grep drm'
	if grep -v 'drm.debug=' /proc/cmdline &>/dev/null; then
		log_write $OF "Warning, enable drm.debug=0xe on boot options line"
	fi
}

x_info() {
	local verify_list
	local CONTENT_FOUND=0

	printlog "X..."
	(( $OPTION_X )) || { echolog Excluded; return 1; }
	OF=x.txt
	addHeaderFile $OF
	case $SLES_VER in
	15*|16*|999)
		MESA="Mesa Mesa-32bit Mesa-demo-x Mesa-libEGL1 Mesa-libEGL1-32bit Mesa-libGL1 \
		Mesa-libGL1-32bit Mesa-libGLESv2-2 Mesa-libGLESv2-2-32bit Mesa-libglapi0 \
                Mesa-libglapi0-32bit"

		XORG_APPS="appres autocutsel bitmap editres fonttosfnt glamor  iceauth listres luit \
                mkfontdir mkfontscale numlockx rendercheck rgb s2tc sessreg setxkbmap \
                viewres x11-tools x11perf xauth xbacklight xbitmaps xclock xconsole \
                xcursorgen xdm xdmbgrd xdpyinfo xev xeyes xfd xfontsel xfsdump xfsprogs \
                xgamma xhost xinit xinput xkbcomp xkbevd xkbprint xkbutils xkill xlogo \
                xlsatoms xlsclients xlsfonts xmag xmessage xmodmap intel-gpu-tools xprop \
                xrandr xrdb xrestop xscope xset xsetmode xsetpointer xsetroot xvinfo xwd \
                xwininfo"

		XORG_FONTS="gnu-unifont-bitmap-fonts efont-unicode-bitmap-fonts baekmuk-bitmap-fonts \
                arabic-bitmap-fonts intlfonts-arabic-bitmap-fonts \
                intlfonts-chinese-big-bitmap-fonts intlfonts-chinese-bitmap-fonts \
                intlfonts-euro-bitmap-fonts intlfonts-japanese-big-bitmap-fonts \
                intlfonts-japanese-bitmap-fonts terminus-bitmap-fonts \
                wqy-bitmap-fonts x11-japanese-bitmap-fonts"

		XORG_LIBS="libGLU1 libGLw1 libICE6 libSM6 libX11-6 libX11-data libX11-xcb1 libXRes1 \
                libXau6 libXaw3d8 libXaw7 libXaw8 libXcomposite1 libXcursor1  libXdamage1 \
                libXdmcp6 libXevie1 libXext6 libXfixes3 libXfont1 libXfontcache1 libXft2 \
                libXi6 libXinerama1 libXiterm1 libXmu6 libXmuu1 libXp6 libXpm4 libXprintUtil1 \
                libXrandr2 libXrender1 libXt6 libXt6-32bit libXtst6 libXvMC1 libXxf86dga1 \
                libXxf86misc1 libXxf86vm1 libdmx1 libdrm2  libXv1 libdrm_intel1 \
                libdrm_nouveau2 libdrm_radeon1 libevdev-tools libevdev2 libfontenc1 \
                libgssglue1 libmtdev1 libpciaccess0 libsmartcols1 libsmbclient-raw0 \
                libsmbclient0 libsmbconf0 libsmbios2 libsmbldap0 libsmi libsmi2 libvdpau1 \
                libxcb-dri2-0 libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
                libxcb-randr0 libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 \
                libxcb-sync1 libxcb-util1 libxcb-xf86dri0 libxcb-xfixes0 libxcb-xkb1 \
                libxcb-xv0 libxcb1 libxkbfile1 libxtables10"

		XORG_32_LIBS="libGLU1-32bit libGLw1-32bit libICE6-32bit libSM6-32bit libX11-6-32bit \
                libX11-xcb1-32bit libXRes1-32bit libXau6-32bit libXaw3d8-32bit libXaw7-32bit \
                libXcomposite1-32bit libXcursor1-32bit libXdamage1-32bit libXdmcp6-32bit \
                libXext6-32bit libXfixes3-32bit libXft2-32bit libXi6-32bit libXinerama1-32bit \
                libXmu6-32bit libXp6-32bit libXpm4-32bit libXprintUtil1-32bit libXrandr2-32bit \
                libXrender1-32bit libXxf86vm1-32bit libXtst6-32bit libXv1-32bit libdrm2-32bit \
                libfontenc1-32bit libglut3-32bit libdrm_intel1-32bit libdrm_nouveau2-32bit \
                libdrm_radeon1-32bit libgssglue1-32bit libpciaccess0-32bit \
                libsmbclient-raw0-32bit libsmbclient0-32bit libsmbconf0-32bit \
                libsmbldap0-32bit libvdpau1-32bit libxcb-dri2-0-32bit libxcb-glx0-32bit \
                libxcb-render0-32bit libxcb-shm0-32bit libxcb-util1-32bit libxcb-xfixes0-32bit \
                libxcb-xkb1-32bit libxcb1-32bit libxkbfile1-32bit"

		XORG_DRIVERS="vaapi-intel-driver xf86-input-evdev xf86-input-synaptics xf86-input-vmmouse \
                xf86-input-void xf86-input-wacom xf86-video-ati xf86-video-cirrus \
                xf86-video-fbdev xf86-video-intel xf86-video-mga xf86-video-modesetting \
                xf86-video-nouveau xf86-video-nv xf86-video-qxl xf86-video-v4l \
                xf86-video-vesa xf86-video-vmware"

                XORG_STUFF="xcursor-themes xkeyboard-config xkeyboard-config-lang xorg-docs"

                XORG_DUMMY="xorg-x11 xorg-x11-driver-input xorg-x11-driver-video xorg-x11-essentials \
                xorg-x11-fonts xorg-x11-fonts-core xorg-x11-libX11-ccache xorg-x11-libs \
                xorg-x11-server xorg-x11-server-extra"

		XORG_PACKAGES="$MESA $XORG_APPS $XORG_FONTS $XORG_LIBS $XORG_32_LIBS $XORG_DRIVERS $XORG_STUFF"
		for i in $XORG_PACKAGES xorg-x11-Xvnc tigervnc xorg-x11-server
		do
			rpm -q $i &> /dev/null && verify_list="$verify_list $i"
		done
		[[ -n "$verify_list" ]] && rpm_verify $OF "$verify_list"
		if rpm -q xorg-x11-server &>/dev/null
		then
			CONTENT_FOUND=1
			log_cmd $OF 'bash -c "for i in /sys/class/input/input*; do echo -n \"\$i: \"; echo -n \$i/event* \"  \" | sed -e \"s#\$i/##\"; cat \$i/name; done"'
			log_cmd $OF 'ls -al /dev | egrep "video.*"'
			log_cmd $OF 'mokutil --sb-state'
			if log_cmd $OF 'cat /proc/fb'; then
				grep -q "VESA" /proc/fb && timed_log_cmd $OF 'hwinfo --framebuffer'
			fi
			log_cmd $OF 'lspci -nn'

			conf_files $OF /etc/sysconfig/displaymanager /etc/sysconfig/windowmanager /etc/xinetd.d/vnc
			if [[ -e /etc/X11/xorg.conf ]]; then
				xorg_conf=/etc/X11/xorg.conf
				TMPLOG=$ADD_OPTION_LOGS
			elif [[ -d /etc/X11/xorg.conf.d ]]; then
				xorg_conf='/etc/X11/xorg.conf.d/*'
				TMPLOG=0
			fi
			[[ -n "$xorg_conf" ]] && ADD_OPTION_LOGS=$TMPLOG conf_files $OF $xorg_conf
		fi
		if [[ -d /sys/class/drm ]]
		then
			CONTENT_FOUND=1
			if [[ "$xserver_present" == "n" ]]
			then
			log_cmd $OF 'mokutil --sb-state'
			log_cmd $OF 'lspci -nn'
			fi
			drm_sub_info
		fi
		if (( $CONTENT_FOUND > 0 ))
		then
			if (( $ADD_OPTION_LOGS )); then
				log_cmd $OF "journalctl --no-pager --output=short-iso | egrep -e 'gnome|gdm|plasma|kde'"
			else
				log_cmd $OF "journalctl --no-pager --output=short-iso | egrep -e 'gnome|gdm|plasma|kde' | tail -${VAR_OPTION_LINE_COUNT}"
			fi
			echolog Done
		else
			echolog Skipped
		fi
	;;
	*) echolog Skipped ;;
	esac
}

ssh_info() {
	printlog "SSH..."
	(( $OPTION_SSH )) || { echolog Excluded; return 1; }
	OF=ssh.txt
	addHeaderFile $OF
	if rpm_verify $OF openssh
	then
		log_cmd $OF "systemctl status sshd.service"
		conf_files $OF /etc/ssh/sshd_config /etc/ssh/ssh_config /etc/pam.d/sshd
		log_cmd $OF 'ss -nlp | grep sshd'
		echolog Done
	else
		echolog Skipped
	fi
}

slert_info() {
	printlog "SLERT..."
	(( $OPTION_SLERT )) || { echolog Excluded; return 1; }
	OF=slert.txt
	addHeaderFile $OF
	if rpm_verify $OF kernel-rt
	then
		log_cmd $OF "uname -r"
		log_cmd $OF 'systemctl status slert.service'
		log_cmd $OF 'systemctl status cset.service'
		log_cmd $OF "ps -eo pid,user,args,ni,rtprio --sort -rtprio"
		conf_files $OF /etc/slert/setup /proc/cpuinfo /etc/sysconfig/cset /etc/cset.conf
		if [[ -e /proc/irq/default_smp_affinity ]]; then
			conf_files $OF /proc/irq/default_smp_affinity /proc/irq/*/smp_affinity
		fi
		log_write $OF "#==[ Process (thread) RT scheduling ]==============================#"
		for TASK in $(ps axHo pid | sed -e '/PID/d')
		do
			log_cmd $OF "chrt -p $TASK"
		done
		echolog Done
	else
		echolog Skipped
	fi
}

print_info() {
	printlog "Printing..."
	(( $OPTION_PRINT )) || { echolog Excluded; return 1; }
	OF=print.txt
	addHeaderFile $OF
	SKIP=0
	if rpm_verify $OF cups
	then
		log_cmd $OF "systemctl status cups.service"
		log_cmd $OF 'ss -nlp | grep cupsd'
		BEP=$(ls -1 /usr/lib*/cups/backend/parallel 2>/dev/null | head -n1)
		if ! (( $MIN_OPTION_AUTOMOD )); then
			log_write $OF "#==[ Warning ]======================================#"
			log_write $OF "# Autoloading kernel modules disabled. Don't use -k."
			log_write $OF "# Excluding $BEP"
			log_write $OF
		else
			[[ -x "$BEP" ]] && log_cmd $OF "$BEP"
		fi
		BEU=$(ls -1 /usr/lib*/cups/backend/usb 2>/dev/null | head -n1)
		[[ -x "$BEU" ]] && log_cmd $OF "$BEU"
		[[ -d /etc/cups/ppd ]] && PPDFILES=$(find -L /etc/cups/ppd/ -type f) || PPDFILES=""
		conf_files $OF /etc/sysconfig/cups /etc/sysconfig/printer /etc/printcap /etc/cups/cupsd.conf /etc/cups/printers.conf /etc/cups/mime.types /etc/cups/mime.convs $PPDFILES

		[[ -d /etc/cups/ppd ]] && PPDFILES=$(find -L /etc/cups/ppd/ -type f) || PPDFILES=""
		conf_files $OF /etc/sysconfig/printer /etc/printcap /etc/cups/cupsd.conf /etc/cups/printers.conf /etc/cups/mime.types /etc/cups/mime.convs $PPDFILES
		FILES="/var/log/cups/error_log /var/log/cups/error_log.test /tmp/prnlog"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	else
		((SKIP++))
	fi

	if rpm_verify $OF cups-client
	then
		timed_log_cmd $OF 'lpstat -t'
		log_cmd $OF 'lpc status'
	else
		((SKIP++))
	fi

	(( $SKIP < 2 )) && echolog Done || echolog Skipped
}

sar_info() {
	printlog "SAR Files..."
	(( $OPTION_SAR )) || { echolog Excluded; return 1; }
	OF=sar.txt
	addHeaderFile $OF
	SARDIR=/var/log/sa
	SARSCDIR=$LOG/sar
	if rpm_verify $OF sysstat; then
		if [[ -d $SARDIR ]]; then
			log_cmd $OF '/usr/lib64/sa/sa1 1 1'
			FOUND=$(ls -A1 $SARDIR)
			if [[ -n "$FOUND" ]]; then
				mkdir -p $SARSCDIR
				log_entry $OF command "cp $SARDIR/sa* $SARSCDIR"
				if (( $ADD_OPTION_LOGS )); then
					cp $SARDIR/sa* $SARSCDIR &>/dev/null
				else
					log_write $OF "# NOTE: Only the newest $VAR_OPTION_SAR_FILES_LIMIT files are copied"
					log_write $OF "# Use sar -f filename to read included sar files"
					for i in $(ls -A1 $SARDIR/sa* 2>/dev/null | grep -Po '^'$SARDIR'/sar?\K([^\.]+)(?=.*)' | sort -u | tail -$VAR_OPTION_SAR_FILES_LIMIT)
					do
						# copy both binary and plaintext sar files for X files limit pattern
						cp $SARDIR/sa{,r}$i{,.*} $SARSCDIR &>/dev/null
					done
				fi
				echolog Done
			else
				echolog Skipped
			fi
		else
			echolog Skipped
		fi
	else
		echolog Skipped
	fi
}

dns_info() {
	printlog "DNS..."
	(( $OPTION_DNS )) || { echolog Excluded; return 1; }
	SKIP=0
	OF=dns.txt
	addHeaderFile $OF
	if rpm_verify $OF bind; then
		log_cmd $OF 'systemctl status named.service'
		(( $SKIP )) && log_cmd $OF 'ss -nlp | grep named'
		FILES=$(grep ^include /etc/named.conf | cut -d';' -f1 | sed -e 's/"//g'  | awk '{print $2}')
		conf_files $OF /etc/named.conf $FILES /etc/sysconfig/named
		ZDIR=$(grep ^[[:space:]]*directory /etc/named.conf | cut -d';' -f1 | sed -e 's/"//g'  | awk '{print $2}')
		if [[ -n "$ZDIR" ]]; then
			FILES=$(find -L ${ZDIR}/ -mount -type f 2>/dev/null | grep zone | grep -v '/proc/') || unset FILES
			conf_files $OF $FILES
			FILES=$(find -L ${ZDIR}/ -mount -type f 2>/dev/null | egrep -v "localtime|zone" | grep -v '/proc/') || unset FILES
			conf_files $OF $FILES
		fi
		log_cmd $OF "grep named /var/log/warn"
		log_cmd $OF "grep named /var/log/messages"
		echolog Done
	else
		echolog Skipped
	fi
}

dhcp_info() {
	printlog "DHCP..."
	(( $OPTION_DHCP )) || { echolog Excluded; return 1; }
	OF=dhcp.txt
	addHeaderFile $OF
	SKIP=0
	if rpm_verify $OF dhcp-server; then
		log_cmd $OF 'systemctl status dhcpd.service'
		log_cmd $OF 'ss -nlp | grep dhcp'
		conf_files $OF /etc/sysconfig/dhcpd
		conf_files $OF /etc/dhcpd.conf /var/lib/dhcp/db/dhcpd.leases
		log_cmd $OF "grep ' dhcpd' /var/log/warn"
		log_cmd $OF "grep ' dhcpd' /var/log/messages"
		echolog Done
	else
		echolog Skipped
	fi
}

tuned_info() {
	printlog "Tuned..."
	(( $OPTION_TUNED )) || { echolog Excluded; return 1; }
	OF=tuned.txt
	addHeaderFile $OF
	if rpm_verify $OF tuned; then
		log_cmd $OF "systemctl status tuned.service"
		log_cmd $OF "tuned-adm active"
		log_cmd $OF "tuned-adm profile_info"
		FILES=$(find -L /etc/tuned/ -type f 2>/dev/null)
		conf_files $OF $FILES
		FILES=$(find /usr/lib/tuned/ -type f 2>/dev/null | grep '\.conf$')
		conf_files $OF $FILES
		FILES="/var/log/tuned/tuned.log"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		if rpm_verify $OF sapconf; then
			log_cmd $OF "systemctl status sapconf.service"
			FILES="/var/log/sapconf.log"
			(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		fi
		echolog Done
	else
		echolog Skipped
	fi
}

cimom_info() {
	printlog "CIMOM..."
	(( $OPTION_CIMOM )) || { echolog Excluded; return 1; }
	OF=cimom.txt
	addHeaderFile $OF
	SKIP=0
	if rpm_verify $OF openwbem; then
		log_cmd $OF "egrep -i \"cim|provider\" $RPMPATH"
		log_cmd $OF 'systemctl status owcimomd.service'
		conf_files $OF /etc/openwbem/openwbem.conf
		log_cmd $OF 'ls -lR --time-style=long-iso /etc/openwbem/'
		for i in cert key
		do
			unset OWSSLCHECK
			OWSSLCHECK=$(grep "^http_server.SSL_${i}" /etc/openwbem/openwbem.conf | awk '{print $3}')
			if [[ -n "$OWSSLCHECK" ]]; then
				if [[ -L $OWSSLCHECK ]]; then
					log_cmd $OF "readlink -ev $OWSSLCHECK"
				fi
			fi
		done
		log_cmd $OF 'owenumnamespace -u https://localhost/root/cimv2'
		log_cmd $OF 'owenumclassnames -u https://localhost/root/cimv2'
		[[ -f /var/lib/openwbem/loadmof.log ]] && FILES="/var/lib/openwbem/loadmof.log /var/lib/openwbem/loadmof.log.*" || unset FILES
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
	else
		((SKIP++))
	fi
	if rpm_verify $OF sblim-sfcb; then
		log_cmd $OF "egrep -i \"cim|provider\" $RPMPATH"
		log_cmd $OF 'systemctl status sfcb.service'
		log_cmd $OF "ss -nlp | grep sfcb"
		conf_files $OF /etc/sfcb/sfcb.cfg
		log_cmd $OF "ls -lR --time-style=long-iso /etc/sfcb/"
	else
		((SKIP++))
	fi

	(( $SKIP < 2 )) && echolog Done || echolog Skipped
}

ib_info() {
	printlog "InfiniBand..."
	(( $OPTION_IB )) || { echolog Excluded; return 1; }
	OF=ib.txt
	addHeaderFile $OF
	case $SLES_VER in
	15*|16*|999)
		CHK_UTILS=0
		CHK_SRP=0
		CHK_DIAG=0
		CHK_ACM=0
		CHK_OPENSM=0
		IBRPM='rdma-core'
		if rpm_verify $OF $IBRPM; then
			rpm_verify $OF ibutils && CHK_UTILS=1
			rpm_verify $OF srp_daemon && CHK_SRP=1
			rpm_verify $OF infiniband-diags && CHK_DIAG=1
			rpm_verify $OF opensm && CHK_OPENSM=1
			rpm_verify $OF ibacm && CHK_ACM=1

			log_cmd $OF "systemctl status rdma-hw.target"
			log_cmd $OF "systemctl status rdma-sriov.service"
			(( CHK_SRP )) && log_cmd $OF "systemctl status srp_daemon.service"
			(( CHK_OPENSM )) && log_cmd $OF "systemctl status opensm.service"
			(( CHK_ACM )) && log_cmd $OF "systemctl status ibacm.service"

			# Get configuration files
			FILES=$(find -L /etc/rdma/ -type f)
			[[ -d /etc/infiniband ]] && FILES="$FILES $(find -L /etc/infiniband/ -type f)"
			(( CHK_SRP )) && FILES="$FILES /etc/srp_daemon.conf"
			(( CHK_DIAG )) && FILES="$FILES $(find -L /etc/infiniband-diags/ -type f)"
			(( CHK_OPENSM )) && FILES="$FILES /etc/opensm.conf /etc/sysconfig/opensm"
			conf_files $OF $FILES

			if (( CHK_UTILS )); then
				log_cmd $OF 'ibdiagnet'
				log_cmd $OF 'ibdmchk'
			fi
			if (( CHK_DIAG )); then
				log_cmd $OF 'ibaddr'
				log_cmd $OF 'ibstat'
			fi
			if (( CHK_ACM )); then
				log_cmd $OF 'ib_acme -e'
			fi
			log_cmd $OF 'lspci -b'
			log_cmd $OF 'lspci -nn'
			log_cmd $OF 'lsmod'

			FILES=''
			(( CHK_DIAG )) && FILES="$FILES $(find /tmp/ -type f -name \*ibdiagnet\* 2>/dev/null)"
			(( CHK_OPENSM )) && FILES="$FILES /var/log/opensm.log"
			(( CHK_ACM )) && FILES="$FILES /var/log/ibacm.log"
			(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
			echolog Done
		else
			echolog Skipped
		fi
		;;
	*) echolog Skipped ;;
	esac
}

web_info() {
	printlog "Web..."
	(( $OPTION_WEB )) || { echolog Excluded; return 1; }
	SKIP=0
	OF=web.txt
	addHeaderFile $OF
	if rpm_verify $OF apache2; then
		log_cmd $OF "systemctl status apache2.service"
		conf_files $OF /etc/sysconfig/apache2 /etc/apache2/httpd.conf
		FILES=$(find -L /etc/apache2/ -type f | grep 'conf$' | grep -v 'httpd.conf')
		conf_files $OF $FILES
		FILES=$(find /var/log/apache2/ -type f)
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		TOMCAT=$(cat $LOG/$RPM_QA_FILE | grep '^tomcat')
		for i in $TOMCAT
		do
			rpm_verify $OF $i
		done
		if [[ -s /etc/sysconfig/j2ee ]]; then
			conf_files $OF /etc/sysconfig/j2ee
			. /etc/sysconfig/j2ee
			conf_files $OF $CATALINA_HOME/conf/server.xml
			FILES="$CATALINA_HOME/logs/catalina.out $CATALINA_HOME/logs/localhost_log*"
			(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		fi
		echolog Done
	else
		echolog Skipped
	fi
}

hppsp_info() {
	OFPSP=psp.txt
	if [[ -s /var/log/hppldu.log ]]; then
		addHeaderFile $OFPSP
		PSPFILES="/var/log/hppldu.log"
		(( $ADD_OPTION_LOGS )) && log_files $OFPSP 0 $PSPFILES || log_files $OFPSP $VAR_OPTION_LINE_COUNT $PSPFILES
		if [[ -d /var/hp ]]; then
			PSPCFILES="$(find /var/hp/ -type f)"
			conf_files $OFPSP $PSPCFILES
		fi
	fi
}

sysfs_info() {
	printlog "SYSFS..."
	(( $OPTION_SYSFS )) || { echolog Excluded; return 1; }
	OF=sysfs.txt
	addHeaderFile $OF
	log_entry $OF command "/bin/find /sys | sed -e 's/\\/\\\\/g' | xargs ls -ld --time-style=long-iso"
	/bin/find /sys | sed -e 's/\\/\\\\/g' | xargs ls -ld --time-style=long-iso >> ${LOG}/${OF} 2>&1
	log_write $OF
	if log_cmd $OF "systool"; then
		for ITEM in $(systool)
		do
			case $ITEM in
			Supported) SBUS=0; SCLS=0; SDEV=0; SMOD=0 ;;
			buses:) SBUS=1; continue ;;
			classes:) SCLS=1; continue ;;
			devices:) SDEV=1; continue ;;
			modules:) SMOD=1; continue ;;
			esac
			if (( SBUS )); then
				# collecting memory info from sysfs can be time consuming
				# skip it on systems with 16TB  or ram or more unless exhaustive
				# option is used
				if [[ $ITEM == "memory" ]]; then
					mem=$(grep 'MemTotal' /proc/meminfo | awk '{print $2}')
					(( $mem > 16000000000 )) && (( $VAR_OPTION_EXHAUSTIVE_MEM == 0 )) && continue
					echonlog "Please Wait..."
					echonlog "Memory"
				fi
				log_cmd $OF "systool -vb $ITEM"
			elif (( SCLS )); then
				log_cmd $OF "systool -vc $ITEM"
			elif (( SMOD )); then
				log_cmd $OF "systool -vm $ITEM"
			fi
		done
	fi
	echolog Done
}

transactional_info() {
	printlog "Transactional Update..."
	(( $OPTION_TRANSACTIONAL )) || { echolog Excluded; return 1; }
	OF=transactional-update.txt
	addHeaderFile $OF
	if rpm_verify $OF transactional-update; then
		log_cmd $OF "systemctl status transactional-update.service"
		log_cmd $OF "systemctl status transactional-update.timer"
		log_cmd $OF "systemctl list-timers --all"
		conf_files $OF /etc/transactional-update.conf
		conf_files $OF /var/lib/misc/transactional-update.state
		FILES="/var/log/transactional-update.log"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		echolog Done
	else
		echolog Skipped
	fi
}

livepatch_info() {
	printlog "Livepatch..."
	(( $OPTION_LIVEPATCH )) || { echolog Excluded; return 1; }
	OF=livepatch.txt
	addHeaderFile $OF
	SKIP=0
	log_cmd $OF 'rpm -qa | grep livepatch'
	if rpm_verify $OF kernel-livepatch-tools; then
		log_cmd $OF 'klp status'
		log_cmd $OF 'klp -v blocking'
		log_cmd $OF 'klp -v patches'
	else
		((SKIP++))
	fi
	if rpm_verify $OF libpulp-tools; then
		log_cmd $OF 'ulp -v patches'
		log_entry $OF command 'for library in $(find -L /lib64 -type f ); do ulp livepatchable $library; done'
		for library in $(find -L /lib64 -type f )
		do
			ulp livepatchable $library >> $LOG/$OF 2>&1
		done
		log_write $OF
		log_entry $OF command 'for library in $(find -L /usr/lib64 -type f ); do ulp livepatchable $library; done'
		for library in $(find -L /usr/lib64 -type f )
		do
			ulp livepatchable $library >> $LOG/$OF 2>&1
		done
		log_write $OF
	else
		((SKIP++))
	fi
	(( SKIP > 1 )) && echolog Skip || echolog Done
}

email_info() {
	printlog "Email..."
	(( $OPTION_EMAIL )) || { echolog Excluded; return 1; }
	OF=email.txt
	addHeaderFile $OF
	if rpm_verify $OF postfix; then
		EXCLUDE_LIST="/etc/postfix/sasl_passwd"
		log_cmd $OF "systemctl status postfix.service"
		log_cmd $OF "postconf -n"
		log_cmd $OF "postconf -d"
		log_cmd $OF "postqueue -p"
		log_cmd $OF "postqueue -j"
		log_cmd $OF 'bash -c "comm -23 <(postconf -n) <(postconf -d)"'
		FILES=$(find /etc/postfix/ ! -name '*.rpmnew' -type f -exec sh -c 'f=$1; file -bL --mime $f | grep -q "^text/plain" && echo $f' {} {} \; | egrep -v "${EXCLUDE_LIST}" | sort)
		conf_files $OF $FILES
		FILES="/var/log/mail.err /var/log/mail.warn /var/log/mail.info /var/log/mail"
		(( $ADD_OPTION_LOGS )) && log_files $OF 0 $FILES || log_files $OF $VAR_OPTION_LINE_COUNT $FILES
		_sanitize_file $OF
		echolog Done
	else
		echolog Skipped
	fi
}

##############################################################################
#  main 
##############################################################################
RCFILE='/usr/lib/supportconfig/resources/supportconfig.rc'
if [[ -s $RCFILE ]]; then
	. $RCFILE
else
	echo "Error: File not found - $RCFILE"
	exit 1
fi

CURRENTUID=$(id -u)
if (( $CURRENTUID != 0 )); then
	echo "ERROR: You must be logged in as root."
	echo "       $(id)"
	echo
	exit_code 1 "ERROR: You must be logged in as root"
fi

# check for valid conf file
if [[ -s ${SC_CONF:="${CONFIG_DIR}/${CURRENT_SCRIPT}.conf"} ]]; then
	if [[ -x /usr/bin/dos2unix ]]; then
		/usr/bin/dos2unix $SC_CONF &>/dev/null
	else
		sed -i -e 's/\r//g' $SC_CONF &>/dev/null
	fi
	. ${SC_CONF}
fi

log2sys "BEGIN Version: $SVER"
ext_scaling_check
init_plugins on
get_sles_ver
NSA_CHECK=0
ALL_ARGS="$@"
declare -a KV_PAIRS
while getopts :\#AB:CDE:FG:H:I:JLM:N:O:P:QR:S:T:U:W:X:V:abcdef:ghi:klmo:pqr:st:uvwx:yz TMPOPT
do
	case $TMPOPT in
	\:)	clear; title
			case $OPTARG in
			*) echo "ERROR: Missing Argument -$OPTARG"
				;;
			esac
			echo; show_help; exit_code 0 "ERROR: Missing Argument -$OPTARG" ;;
	\?)	clear; title
			case $OPTARG in
			*) echo "ERROR: Invalid Option -$OPTARG"
				;;
			esac
			echo; show_help; exit_code 0 "ERROR: Invalid Options -$OPTARG" ;;
	\#) set_to_min; MIN_OPTION_HC=0; MIN_OPTION_HARDWARE=0; MIN_OPTION_YAST=0; MIN_OPTION_SYSLOGS=0; NSA_CHECK=1; COMPRESS="tgz"; COMPRESS_OPT="zcf" ;;
	A) set_to_all ;;
	B) VAR_OPTION_CUSTOM_ARCH="$OPTARG" ;;
	C) clear; title; echo "Overwriting $SC_CONF with default options."; gen_sysconfig; exit_code 0 ;;
	D) set_to_default ;;
	E) VAR_OPTION_CONTACT_EMAIL="$OPTARG" ;;
	F) get_features; exit_code 0 ;;
	G) VAR_OPTION_GPG_UID="$OPTARG" ;;
	H) VAR_OPTION_PENGINE_FILES_LIMIT=$OPTARG ;;
	I) VAR_OPTION_LINE_COUNT=$OPTARG ;;
	J) VAR_OPTION_EXHAUSTIVE_MEM=1 ;;
	L) ADD_OPTION_FSLIST=1 ;;
	M) VAR_OPTION_CONTACT_TERMINALID="$OPTARG" ;;
	N) VAR_OPTION_CONTACT_NAME="$OPTARG" ;;
	O) VAR_OPTION_CONTACT_COMPANY="$OPTARG" ;;
	P) VAR_OPTION_CONTACT_PHONE="$OPTARG" ;;
	Q) VAR_OPTION_SILENT=1 ;;
	R) VAR_OPTION_LOG_DIRS="$OPTARG" ;;
	S) VAR_OPTION_SAR_FILES_LIMIT=$OPTARG ;;
	T) VAR_OPTION_BIN_TIMEOUT_SEC=$OPTARG ;;
	U) VAR_OPTION_UPLOAD_TARGET="$OPTARG" && UPLOAD_TARBALL=1 ;;
	V) KV_PAIRS+=("${OPTARG}") ;;
	W) VAR_OPTION_CONTACT_STOREID="$OPTARG" ;;
	X) VAR_OPTION_MSG_MAXSIZE=$OPTARG ;;
	a) UPLOAD_TARBALL=1; VAR_OPTION_UPLOAD_TARGET=${VAR_OPTION_UPLOAD_TARGET_ALT} ;;
	b) VAR_OPTION_SBM=1 ;;
	c) ADD_OPTION_LOCAL_ONLY=1 ;;
	d) ADD_OPTION_MINDISK=1 ;;
	e) (( EXT_SCALING_DISABLED )) || log2sys "Extended Scaling: Disabled with -e"
		EXT_SCALING_DISABLED=1 ;;
	f) FROM_DIRECTORY=$OPTARG  && USE_SAVED_LOGS_ONLY=1;;
	g) COMPRESS="tgz"; COMPRESS_OPT="zcf" ;;
	h) title; show_help; exit_code 0 ;;
	i) SELECTED_FEATURE_LIST=$OPTARG; set_to_min; selected_features on ;;
	k) MIN_OPTION_AUTOMOD=0 ;;
	l) ADD_OPTION_LOGS=1 ;;
	m) set_to_min ;;
	o) SELECTED_FEATURE_LIST=$OPTARG; toggle_features ;;
	p) init_plugins off ;;
	q) VAR_OPTION_UNIQUE_FILE=1 ;;
	r) CONTACT_SRNUM=$OPTARG;
		if valid_srnum; then
			BASE="${ARCHIVE_PREFIX}%r_%B"
		else
			clear; title
			echo "ERROR: Invalid SR Number, -${TMPOPT} $CONTACT_SRNUM"
			echo "       Must be a numeric value only"
			echo; show_help; exit_code 2
		fi ;;
	s) ADD_OPTION_SLP=1 ;;
	t) TARGET_DIRECTORY=$OPTARG && SAVE_LOGS_ONLY=1;;
	u) UPLOAD_TARBALL=1 ;;
	v) ADD_OPTION_RPMV=1 ;;
	w) VAR_OPTION_WAIT_TRACE=1; VAR_OPTION_SBM=1 ;;
	x) SELECTED_FEATURE_LIST=$OPTARG; selected_features off ;;
	y) ADD_OPTION_MAXYAST=1 ;;
	z) COMPRESS="tbz"; COMPRESS_OPT="jcf" ;;
	esac
done

(( $ADD_OPTION_LOGS )) && ADD_OPTION_MAXYAST=1

umask 0077
log2sys "Initialize"

if [[ -n "$TARGET_DIRECTORY" ]]; then
	VAR_OPTION_LOG_DIRS=$TARGET_DIRECTORY
fi

# Uploaded tarball filenames should be unique
if (( UPLOAD_TARBALL )); then
	VAR_OPTION_UNIQUE_FILE=1
fi

# Add custom tar ball name element
if [[ -n $VAR_OPTION_CUSTOM_ARCH ]]; then
	TMP=$(echo "$VAR_OPTION_CUSTOM_ARCH" | sed -e 's/ /_/g')
	BASE="${ARCHIVE_PREFIX}${TMP}"
fi

if (( VAR_OPTION_UNIQUE_FILE )); then
	NOTFOUND=$(echo $BASE | grep '%u')
	[[ -z "$NOTFOUND" ]] && BASE="${BASE}_%u" #add UID if not present already
fi

if [[ -n "$FROM_DIRECTORY" ]]; then
	if [[ -s ${FROM_DIRECTORY}/${BASIC_ENVF} ]]; then
		VAR_OPTION_LOG_DIRS=$(dirname ${FROM_DIRECTORY} 2>/dev/null)
		BASE=$(basename ${FROM_DIRECTORY} 2>/dev/null)
	else
		VAR_OPTION_LOG_DIRS=$FROM_DIRECTORY
		TBASE=$(ls -1td ${FROM_DIRECTORY}/*/ 2>/dev/null | egrep 'scc_|nts_' | head -n1)
		BASE=$(basename $TBASE 2>/dev/null)
	fi
fi

for LOG in $VAR_OPTION_LOG_DIRS
do
	# If a full path was not assigned, the cwd will be prepended to the LOG path
	VALID_LOG=$(echo $LOG | grep '^/')
	if [[ -z "$VALID_LOG" ]]; then
		VALID_LOG=$(echo $LOG | grep '^\./')
		CURRENT_PATH="$(pwd)"
		if [[ -n "$VALID_LOG" ]]; then
			LOG="${CURRENT_PATH}/${LOG:2}"
		else
			LOG="${CURRENT_PATH}/${LOG}"
		fi
	fi
	normalize_base
	# Create the paths
	if (( USE_SAVED_LOGS_ONLY )); then
		if [[ -n $BASE ]]; then
			LOG=${LOG}/${BASE}
		else
			echo "ERROR: Missing or invalid supportconfig directory in -f $LOG"
			LOGERROR=1
		fi
	else
		check_log_dir
		LOG=${LOG}/${BASE}
		if mkdir -p $LOG &>/dev/null; then 
			unset LOGERROR
			break
		else
			echo "ERROR: Cannot create $LOG"
			LOGERROR=1
		fi
	fi
done

if (( $LOGERROR )); then
	echo
	exit_code 3
fi
export LOG CSFILE

if (( $USE_SAVED_LOGS_ONLY != 1 )); then

	if ! (( $VAR_OPTION_SILENT )); then
		if ! (( $VAR_OPTION_SBM )); then
			clear
		fi
	fi
	(( $VAR_OPTION_SILENT )) && title >> $LOG/$BASIC_ENVF || title | tee -a $LOG/$BASIC_ENVF
	if run_status; then
		echo "Error: A supportconfig instance is already running, PID $(cat ${RUN_PID_FILE})"
		echo
		exit_code 10
	else
		run_status start
	fi

	RPM_QA_FILE_PATH=$(mktemp ${LOG}/rpm_qa.XXXXXXXXXX)
	RPM_DIST_FILE_PATH=$(mktemp ${LOG}/rpm_dist.XXXXXXXXXX)
	RPM_QA_FILE=$(basename $RPM_QA_FILE_PATH)
	RPM_DIST_FILE=$(basename $RPM_DIST_FILE_PATH)

	addHeaderFile $CSFILE
	log_entry $CSFILE note "Privacy Statement"
	log_write $CSFILE "Detailed system information and logs are collected and organized in a"
	log_write $CSFILE "manner that helps reduce service request resolution times. Private system"
	log_write $CSFILE "information can be disclosed when using this tool. If this is a concern,"
	log_write $CSFILE "please prune private data from the log files. Several startup options"
	log_write $CSFILE "are available to exclude more sensitive information. Supportconfig data is"
	log_write $CSFILE "used only for diagnostic purposes and is considered confidential information."
	log_write $CSFILE "See http://www.suse.com/company/policies/privacy/"
	log_write $CSFILE
	rpm_verify ${CSFILE} supportutils

	echolog "Gathering system information"
	log_write ${CSFILE}	"  Script Version:       ${SVER}"
	log_write ${CSFILE}	"  Script Date:          ${SDATE}"
	echolog 	    	"  Data Directory:       ${LOG}"
    log_write ${CSFILE} "  Environment Value:    $SLES_VER"
	log_write ${CSFILE} "  Command with Args:    $0 $ALL_ARGS"
	log_write ${CSFILE} "  FORCE_OPTION_PAM:     $FORCE_OPTION_PAM"
	log_write ${CSFILE} "  EXT_SCALING_DISABLED: $EXT_SCALING_DISABLED"
	[[ -s $SC_CONF ]] && log_write ${CSFILE} "  Using Options:        $SC_CONF"

	echolog
	log2sys "Data Directory: ${LOG}"
	log2sys "Supportconfig Args: $ALL_ARGS"

	log_options

	basic_healthcheck	#Minimum Requirement MIN_OPTION_HC
	rpm_info			#Minimum Requirement MIN_OPTION_RPM
	basic_environment	#Minimum Requirement MIN_OPTION_ENV
	open_files
	module_info
	memory_info
	disk_info
	btrfs_info
	transactional_info
	tuned_info
	yast_files			#Minimum Requirement MIN_OPTION_YAST
	fslist_info
	audit_info
	crash_info
	email_info
	ntp_info
	proc_info
	boot_info
	plymouth_info
	slert_info
	update_info
	nvme_info
	bpf_info
	smt_info
	ha_info
	ocfs2_info
	gfs2_info
	drbd_info
	haproxy_info
	pam_info
	ldap_info
	sssd_info
	cimom_info
	environment_info
	root_shell_history_info
	etc_info
	sysconfig_info
	sysfs_info
	systemd_info
	docker_info
	podman_info
	(( SLES_VER < 160 )) && cron_info
	dbus_info
	udev_info
	lvm_info
	soft_raid_info
	mpio_info
	net_info
	web_info
	ib_info
	dns_info
	dhcp_info
	slp_info
	ssh_info
	iscsi_info
	samba_info
	nfs_info
	autofs_info
	sar_info
	if grep 'security=selinux' /proc/cmdline &> /dev/null; then
		selinux_info
		rm -f $AARPTMP &> /dev/null
	elif grep 'security=apparmor' /proc/cmdline &> /dev/null; then
		apparmor_info
	else
		apparmor_info
		selinux_info
	fi
	x_info
	print_info
	smartmon_info
	[[ -s ${FSLIST_ADD_FILE} ]] && fslist_ufiles_info
	livepatch_info
	hardware_info		#Minimum Requirement MIN_OPTION_HARDWARE
	rpm_full_verify
	exec_plugins
	(( OPTION_MOD )) && post_lsmod_list
	log2sys "Finished Gathering"
	messages_file		#Minimum Requirement MIN_OPTION_SYSLOGS
	localwarn_file
	write_xml_file

	rm -f $LOG/$RPM_QA_FILE $LOG/$RPM_DIST_FILE
	timed_cmd_cleanup
	(( $VAR_OPTION_SILENT )) || { echo; }

else
	(( $VAR_OPTION_SILENT )) || { clear; title; }
fi

# don't continue if SAVE_LOGS_ONLY is set
(( $SAVE_LOGS_ONLY )) && exit_code 0;


# creating tar ball for NTS
TARBALL=${LOG}.${COMPRESS}
log2sys "Creating Tar Ball"
if ! (( $VAR_OPTION_SILENT )); then
	if (( $VAR_OPTION_SBM )); then
		echo 'Creating Tar Ball...'
	else
		echo 'Creating Tar Ball'
	fi
fi

cd $LOG
cd ..
wait_trace_on -t "tar ${COMPRESS_OPT} ${TARBALL} --mode='ug+rw' ${BASE}/*"
tar ${COMPRESS_OPT} ${TARBALL} --mode='ug+rw' ${BASE}/*
LOGSIZE=$(ls -lh ${TARBALL} | awk '{print $5}')
wait_trace_off -t
wait_trace_on -t "md5sum $TARBALL"
md5sum $TARBALL | awk '{print $1}' > ${TARBALL}.md5
LOGMD5=$(cat ${TARBALL}.md5)
wait_trace_off -t

rm -rf $LOG

if ! (( $VAR_OPTION_SILENT )); then
cat << EOF1

==[ DONE ]===================================================================
  Log file tar ball: ${TARBALL}
  Log file size:     ${LOGSIZE}
  Log file md5sum:   ${LOGMD5}
=============================================================================


EOF1
fi

trap "{ echo TERMINATED BY USER; echo; exit 5; }" SIGINT
trap "{ echo SKIPPED BY USER; return 4; }" SIGQUIT

[[ -n "$VAR_OPTION_GPG_UID" ]] && encrypt_tarball
upload_tarball
remove_local_tarball
run_status stop
log2sys "END"


