#!/bin/sh
# tlp - display power save and usb autosuspend status
#
# Copyright (c) 2018 Thomas Koch <linrunner at gmx.net>
# This software is licensed under the GPL v2 or later.

# --- Constants

readonly LIBDIR="/usr/share/tlp"
readonly LIBS="tlp-functions tlp-rf-func"

readonly TLPUSB=tlp-usblist
readonly TLPPCI=tlp-pcilist

readonly SMARTCTL=smartctl
readonly LSBREL=lsb_release

readonly ASPM=/sys/module/pcie_aspm/parameters/policy
readonly NMIWD=/proc/sys/kernel/nmi_watchdog
readonly WQPE=/sys/module/workqueue/parameters/power_efficient

readonly IBMTHERMAL=/proc/acpi/ibm/thermal
readonly CORETEMP_DIRS="
/sys/devices/platform/coretemp.0
/sys/devices/platform/coretemp.0/hwmon/hwmon*"
readonly IBMFAN=/proc/acpi/ibm/fan
readonly HWMONFAN_DIRS="
/sys/class/hwmon/hwmon*/device
/sys/class/hwmon/hwmon*"

readonly JOURNALCTL=journalctl
readonly DEBUGLOG=/var/log/debug

readonly SYSTEMD_SERVICES="tlp.service tlp-sleep.service"
readonly RFKILL_SERVICES="systemd-rfkill.service"

readonly EFID=/sys/firmware/efi

readonly RE_ATA_ERROR='ata[0-9]+: SError: {.*CommWake }'

# --- Variables
needs_root_priv=
show_all=1
show_bat=0
show_conf=0
show_disk=0
show_graf=0
show_pcie=0
show_pev=0
show_proc=0
show_psup=0
show_rfkill=0
show_system=0
show_temp=0
show_trace=0
show_usb=0
show_verbose=0
show_warn=0

no_runtimepm=0

# --- Functions

printparm () { # formatted output of sysfile - general
    # $1: format, $2: sysfile, $3: namsg, $4: cutoff
    local format="$1"
    local sysf="$2"
    local namsg="$3"
    local cutoff="$4"
    local val=""

    if [ -f $sysf ]; then
        # sysfile exists
        val=$(cat $sysf 2> /dev/null)
        if [ $? = 0 ]; then
            # sysfile read successful
            if [ -n "$cutoff" ]; then
                val=${val%$cutoff}
            fi
        fi
    fi

    if [ -z "$val" ]; then
        # replace empty value with n/a text
        if [ -n "$namsg" ]; then
            if [ "$namsg" != "_" ]; then
                # use specific n/a text
                format=$( echo $format | sed -r "s/##(.*)##/($namsg)/" | sed -r "s/\[.*\]//" )
            else
                # _ = skip
                sysf=""
            fi
        else
            # empty n/a text, use default text
            format=$( echo $format | sed -r "s/##(.*)##/(not available)/" | sed -r "s/\[.*\]//" )
        fi
        # output n/a text or skip
        [ -n "$sysf" ] && printf "$format\n" "$sysf"
    else
        # non empty value: strip delimiters from format str
        format=$( echo $format | sed -r "s/##(.*)##/\1/" )
        printf "$format\n" "$sysf" "$val"
    fi

    return 0
}

printparm_i915 () { # formatted output of sysfile - i915 kernel module variant
    # $1: sysfile; $2: alternative; $3: 1=psr/0=other
    local sysf val

    # Check if sysfile or alternative exist
    if [ -f $1 ]; then
        sysf=$1
    elif [ -f $2 ]; then
        sysf=$2
    else
        sysf=""
    fi

    if [ -n "$sysf" ]; then
        # sysfile exists, get content
        val=$(cat $sysf 2> /dev/null)
        if [ $? = 0 ]; then
            # sysfile was readable, output content
            printf "%-44s = %2d " "$sysf" "$val"
            # Explain content
            if [ "$val" = "-1" ]; then
                echo "(use per-chip default)"
            else
                echo -n "("
                if [ "$3" = "1" ]; then
                    # enable_psr
                    case $val in
                        0) echo -n "disabled" ;;
                        1) echo -n "enabled" ;;
                        2) echo -n "force link-standby mode" ;;
                        3) echo -n "force link-off mode" ;;
                        *) echo -n "unknown" ;;
                    esac
                else
                    # other parms
                    if [ $(( $val & 1 )) -ne 0 ]; then
                        echo -n "enabled"
                    else
                        echo -n "disabled"
                    fi
                    [ $(( $val & 2 )) -ne 0 ] && echo -n " + deep"
                    [ $(( $val & 4 )) -ne 0 ] && echo -n " + deepest"
                fi
                echo ")"
            fi
        else
            # sysfile was not readable
            printf "%-44s = (not available)\n" "$sysf"
        fi
    fi

    return 0
}

printsysf () { # output a sysfile
    # $1: format; $2: sysfile
    local val

    val=$(cat $2 2> /dev/null)
    if [ $? = 0 ]; then
         # sysfile readable
        printf "$1" "$val"
    else
        # sysfile not readable
        printf "$1" "(not available)"
    fi

    return 0
}

print_tp_batstate () { # print battery charging state with an explanation when
    # a threshold inhibits charging
    # $1: sysfile; $2: 1=ThinkPad battery/0=other
    local sysf val

    # Check if bat state sysfile exists
    if [ -f $1 ]; then
        sysf=$1
    else
        sysf=""
    fi

    if [ -n "$sysf" ]; then
        # bat state sysfile exists, get content
        val=$(cat $sysf 2> /dev/null)
        if [ $? = 0 ]; then
            # sysfile was readable, output content
            printf "%-59s = %s" "$sysf" "$val"
            # Explain content if necessary
            case $val in
                Unknown) # "Unknown" means a threshold forbids charging
                    printf " (threshold effective)\n"
                    ;;

                *) # Nothing to do
                    printf "\n"
                    ;;
            esac
        else
            # sysfile was not readable
            printf "%-59s = (not available)\n" "$sysf"
        fi
    else
        # sysfile nonexistent
        printf "%-59s = (not available)\n" "$1"
    fi

    return 0
}

print_tpacpi_thresholds () { # formatted output of ThinkPad charging thresholds
    # - tpcapi-bat variant
    # $1: BAT0/BAT1; $2: bat # = 1/2
    local start_thresh stop_thresh force

    read_tpacpi_threshold ST $2
    start_thresh=$?
    if [ $start_thresh -ne 255 ]; then
        [ $start_thresh -eq 0 ] && start_thresh=96
        printf "%-59s = %6d [%%]\n" "tpacpi-bat.${1}.startThreshold" "$start_thresh"
    else
        printf "%-59s = (not available)\n" "tpacpi-bat.${1}.startThreshold"
    fi

    read_tpacpi_threshold SP $2
    stop_thresh=$?
    if [ $stop_thresh -ne 255 ]; then
        [ $stop_thresh -eq  0 ] && stop_thresh=100
        printf "%-59s = %6d [%%]\n" "tpacpi-bat.${1}.stopThreshold" "$stop_thresh"
    else
        printf "%-59s = (not available)\n" "tpacpi-bat.${1}.stopThreshold"
    fi

    get_force_discharge $2; force=$?
    if [ $force -ne 2 ]; then
        printf "%-59s = %6d\n" "tpacpi-bat.${1}.forceDischarge" "$force"
    else
        printf "%-59s = %s\n" "tpacpi-bat.${1}.forceDischarge" "(not available)"
    fi

    return 0
}

print_file_modtime_and_age () { # show a file's last modification time
    #  and age in secs -- $1: file
    local mtime age

    if [ -f $1 ]; then
        mtime=$(date +%X -r $1)
        age=$(( $(date +%s) - $(date +%s -r $1) ))
        printf '%s, %6d sec(s) ago' "$mtime" "$age"
    else
        printf "unknown"
    fi
}

print_saved_powerstate () { # read and print saved state
    case "$(cat $PWRRUNFILE 2> /dev/null)" in
        0) echo "AC" ;;
        1) echo "battery" ;;
        *) echo "unknown" ;;
    esac

    return 0
}

check_ata_errors () { # check kernel log for ata errors
    # (possibly) caused by SATA_LINKPWR_ON_AC/BAT != max_performance
    # stdout: error count

    if wordinlist $SATA_LINKPWR_ON_BAT "min_power medium_power" || \
       wordinlist $SATA_LINKPWR_ON_AC "min_power medium_power"; then
        # config values != max_performance exist --> check kernel log

        # count matching error lines
        echo $( dmesg | egrep -c "${RE_ATA_ERROR}" 2> /dev/null )
    else
        # no values in question configured
        echo "0"
    fi

    return 0
}

# @stdout glob_files ( glob_pattern, dir[, dir...] )
#
#  Nested for-loop that applies a glob expression to several directories
#  (or file path prefixes) and prints matching file paths to stdout.
#
glob_files () {
    [ -n "${1-}" ] || return 64
    local glob_pattern file_iter

    glob_pattern="${1}"

    while shift && [ $# -gt 0 ]; do
        for file_iter in ${1}${glob_pattern}; do
            [ ! -f "${file_iter}" ] || echo "${file_iter}"
        done
    done
}

read_args () { # read command line arguments
    for a in $*; do
        case $a in
            "-b"|"--battery")
                show_all=0
                show_bat=1
                needs_root_priv=1
                ;;

            "-c"|"--config")
                show_all=0
                show_conf=1
                : ${needs_root_priv:=0}
                ;;

            "-d"|"--disk")
                show_all=0
                show_disk=1
                needs_root_priv=1
                ;;

            "-e"|"--pcie")
                show_all=0
                show_pcie=1
                : ${needs_root_priv:=0}
                ;;

            "-g"|"--graphics")
                show_all=0
                show_graf=1
                : ${needs_root_priv:=0}
                ;;

            "-p"|"--processor")
                show_all=0
                show_proc=1
                needs_root_priv=1
                ;;

            "-r"|"--rfkill")
                show_all=0
                show_rfkill=1
                : ${needs_root_priv:=0}
                ;;

            "-s"|"--system")
                show_all=0
                show_system=1
                : ${needs_root_priv:=0}
                ;;

            "-t"|"--temp")
                show_all=0
                show_temp=1
                : ${needs_root_priv:=0}
                ;;

            "-u"|"--usb")
                show_all=0
                show_usb=1
                : ${needs_root_priv:=0}
                ;;

            "-v"|"--verbose")
                show_verbose=1
                ;;

            "-w"|"--warn")
                show_all=0
                show_warn=1
                : ${needs_root_priv:=0}
                ;;

            "-P"|"--pev")
                show_all=0
                show_pev=1
                needs_root_priv=1
                ;;

            "--psup")
                show_all=0
                show_psup=1
                : ${needs_root_priv:=0}
                ;;

            "-T"|"--trace")
                show_all=0
                show_trace=1
                needs_root_priv=1
                ;;

            *)
                echo "Usage: tlp-stat [ -b | --battery   | -c | --config    |"
                echo "                  -d | --disk      | -e | --pcie      |"
                echo "                  -g | --graphics  | -p | --processor |"
                echo "                  -r | --rfkill    | -s | --system    |"
                echo "                  -t | --temp      | -u | --usb       |"
                echo "                  -w | --warn      | -v | --verbose   |"
                echo "                  -P | --pev       |    | --psup      |"
                echo "                  -T | --trace ]"
                exit 3
                ;;
        esac
    done
}

# --- Source libraries
for lib in $LIBS; do
    if [ ! -f $LIBDIR/$lib ]; then
        echo "Error: missing function library \'$LIBDIR/$lib\'." 1>&2
        exit 1
    fi
    . $LIBDIR/$lib
done

# --- MAIN
add_sbin2path

read_args $*
: ${needs_root_priv:=1}

# inhibit trace output
nodebug=1

# check for and read conffile
read_defaults
conf_present=$?

# check prerequisites
if [ "$needs_root_priv" = "1" ]; then
    check_root
    load_modules $MOD_MSR $MOD_TEMP
    check_thinkpad
    check_tpacpi
    check_tpsmapi
fi

echo "--- TLP $TLPVER --------------------------------------------"
echo

# --- show configuration
if [ "$show_conf" = "1" ] || [ "$show_all" = "1" ]; then
    if [ $conf_present -eq 0 ]; then
        echo "+++ Configured Settings: $CONFFILE"
        egrep -v '^#|^\s*$' $CONFFILE
        echo
    else
        echo "Error: config file $CONFFILE not present." 1>&2
        echo
    fi
fi # show_conf

if [ "$show_system" = "1" ] || [ "$show_all" = "1" ] ; then
    # --- show system info
    echo "+++ System Info"

    echo "System         = $( read_dmi sys_vendor product_version product_name )"
    echo "BIOS           = $( read_dmi bios_version )"

    # --- show release & kernel info
    cmd_exists $LSBREL && echo "Release        = $($LSBREL -d -s)"
    echo "Kernel         = $(uname -r -m -v)"
    printparm "%-14s = %s" /proc/cmdline

    # --- show init system info
    if check_systemd; then
        echo "Init system    = systemd $(systemd --version 2> /dev/null | sed -rn 's/systemd ([0-9]+)/v\1/p')"
    elif check_upstart; then
        echo "Init system    = upstart"
    elif check_openrc; then
        echo "Init system    = openrc"
    else
        echo "Init system    = sysvinit"
    fi
    if [ -d $EFID ]; then
        echo "Boot mode      = UEFI"
    else
        echo "Boot mode      = BIOS (CSM, Legacy)"
    fi
    echo

    # --- show TLP status
    echo "+++ TLP Status"
    if [ "$TLP_ENABLE" = "1" ]; then
        printf "State          = enabled\n"
    else
        printf "State          = disabled\n"
    fi

    # --- show last invocation time
    printf "Last run       = %s\n" "$(print_file_modtime_and_age ${LOCKFILE}_tlp)"

    # --- show actual power mode
    printf "Mode           = %s\n" "$(print_saved_powerstate)"

    # ---- show actual power source
    get_sys_power_supply
    case $? in
        0) printf "Power source   = AC\n" ;;
        1) printf "Power source   = battery\n" ;;
        *) printf "Power source   = unknown\n" ;;
    esac
    echo

    # -- check systemd service units status
    if check_systemd; then
        cnt=0
        for su in $SYSTEMD_SERVICES; do
            if ! $SYSTEMCTL is-enabled $su > /dev/null 2>&1 ; then
                echo "Notice: $su is not enabled -- invoke \"systemctl enable $su\" to correct this!"
                cnt=$((cnt+1))
            fi
        done
        for su in $RFKILL_SERVICES; do
            ise=$($SYSTEMCTL is-enabled $su 2> /dev/null)
            if [ -n "$ise" ] && [ "$ise" != "masked" ]; then
                echo "Notice: $su is not masked -- invoke \"systemctl mask $su\" to correct this!"
                cnt=$((cnt+1))
            fi
        done
        [ $cnt -gt 0 ] && echo
    fi

    # -- show warning if l-m-t detected
    check_laptop_mode_tools

fi # show_system

if [ "$show_proc" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show cpu info
    echo "+++ Processor"
    sed -rn 's/model name[ \t]+: (.+)/CPU model      = \1/p' /proc/cpuinfo | head -1
    echo

    # -- show scaling gov and freq info
    for cpuf in /sys/devices/system/cpu/cpu*/cpufreq; do
        if [ -f $cpuf/scaling_driver ]; then
            printparm "%-54s = ##%s##" $cpuf/scaling_driver
            printparm "%-54s = ##%s##" $cpuf/scaling_governor
            printparm "%s = ##%s##" $cpuf/scaling_available_governors _

            if [ -f $cpuf/scaling_min_freq ]; then
                printf "%-54s = %8d [kHz]\n" "$cpuf/scaling_min_freq" "$(cat $cpuf/scaling_min_freq 2> /dev/null)"
            fi

            if [ -f $cpuf/scaling_max_freq ]; then
                printf "%-54s = %8d [kHz]\n" "$cpuf/scaling_max_freq" "$(cat $cpuf/scaling_max_freq 2> /dev/null)"
            fi

            if [ -f $cpuf/scaling_available_frequencies ]; then
                printf "%s = " "$cpuf/scaling_available_frequencies"
                for freq in $(cat $cpuf/scaling_available_frequencies 2> /dev/null); do
                    printf "%s " "$freq"
                done
                printf "[kHz]\n"
            fi

            if [ -f $cpuf/energy_performance_preference ]; then
                printparm "%s = ##%s##" $cpuf/energy_performance_preference
            fi
            if [ -f $cpuf/energy_performance_available_preferences ]; then
                printparm "%s = ##%s##" $cpuf/energy_performance_available_preferences
            fi

            printf "\n"
        fi
    done

    check_intel_pstate

    if [ $intel_pstate -eq 1 ]; then
        # show Intel P-state info
        printparm "%-54s = ##%3d## [%%]" $CPU_MIN_PERF_PCT
        printparm "%-54s = ##%3d## [%%]" $CPU_MAX_PERF_PCT
        printparm "%-54s = ##%3d##"      $CPU_TURBO_PSTATE
        printparm "%-54s = ##%3d## [%%]" $INTEL_PSTATED/turbo_pct
        printparm "%-54s = ##%3d##"      $INTEL_PSTATED/num_pstates

    elif [ -f $CPU_BOOST_ALL_CTRL ]; then
        # show turbo boost info
        get_sysval $CPU_BOOST_ALL_CTRL; boost=$?

        # simple test for attribute "w" doesn't work, so actually write
        if { printf '%s\n' "$boost" > $CPU_BOOST_ALL_CTRL; } 2> /dev/null; then
            printparm "%-54s = ##%d##" $CPU_BOOST_ALL_CTRL
        else
            printparm "%-54s = ##%d## (cpu not supported)" $CPU_BOOST_ALL_CTRL
        fi
    else
         printparm "%-54s = (not available)" $CPU_BOOST_ALL_CTRL
    fi

    # --- show sched power save info
    for pool in mc smp smt; do
        sdev="/sys/devices/system/cpu/sched_${pool}_power_savings"
        printparm "%-54s = ##%d##" $sdev _
    done
    echo

    # --- show x86 energy perf policy info
    if cmd_exists $ENERGYPERF; then
        # check CPU support
        $ENERGYPERF -r > /dev/null 2>&1
        case $? in
            0)  # parse x86_energy_perf_policy output:
                # - replace numbers with descriptive strings
                # - remove ":"
                # - indent and align
                $ENERGYPERF -r 2>/dev/null | \
                    sed -r 's/://;
                            s/(0x0000000000000000|EPB 0)/performance/;
                            s/(0x0000000000000004|EPB 4)/balance-performance/;
                            s/(0x0000000000000006|EPB 6)/default/;
                            s/(0x0000000000000008|EPB 8)/balance-power/;
                            s/(0x000000000000000f|EPB 15)/power/' | \
                    awk '{ printf "x86_energy_perf_policy.%-31s = %s %s\n", $1, $2, $3; }'
                ;;

            1) echo "x86_energy_perf_policy: unsupported CPU." ;;
            2) echo "x86_energy_perf_policy: program for your kernel not installed." ;;
            *) echo "x86_energy_perf_policy: not available." ;;
        esac
        echo
    else
        echo "x86_energy_perf_policy: program not installed."
        echo
    fi

    # --- show workqueue power efficient status
    printparm "%-54s = ##%s##" $WQPE

    # --- show nmi watchdog
    printparm "%-54s = ##%d##" $NMIWD
    echo

    # --- show voltages
    echo "+++ Undervolting"
    phc_avail=0
    for cpuf in /sys/devices/system/cpu/cpu*/cpufreq; do
        if [ -f $cpuf/phc_controls ]; then
            phc_avail=1
            printparm "%-58s = ##%s##" $cpuf/phc_controls
            printparm "%-58s = ##%s##" $cpuf/phc_default_controls
            echo
        fi
    done
    if [ $phc_avail = 0 ]; then
        echo "PHC kernel not available."
        echo
    fi
fi # show_proc

if [ "$show_temp" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show temperatures
    echo "+++ Temperatures"
    if [ -f $IBMTHERMAL ]; then
        # use thinkpad-specific sysfile
        echo "$IBMTHERMAL = $(cat $IBMTHERMAL 2> /dev/null | cut -f2  ) [°C]"
    else
        # use sensors
        cmax=0
        for sens in $(glob_files '/temp?*_input' $CORETEMP_DIRS); do
            if grep -q -- 'Physical' ${sens%input}label 2>/dev/null; then
                # package info is available -> ignore remaining sensors
                read -r cmax < $sens
                break
            else
                # core info -> find max value
                read -r ctemp < $sens && [ $ctemp -gt $cmax ] && cmax=$ctemp
            fi
        done
        if [ $cmax -gt 0 ]; then
            perl -e 'printf ("CPU temp               = %5d [°C]\n", '$cmax' / 1000.0);'
        fi

    fi

    # --- show fan speed
    if is_thinkpad && [ -f $IBMFAN ]; then
        # use thinkpad-specific sysfile
        awk '$1 ~ /speed:/ { printf "'$IBMFAN'     = %5d [/min]\n", $2 }' $IBMFAN
    else
        # use hwmon
        have_any_fan=
        for fan in $(glob_files '/fan?*_input' $HWMONFAN_DIRS); do
            if read -r fan_speed < $fan; then
                fan_name="${fan##*/}"; fan_name="${fan_name%_input}"
                have_any_fan=y

                printf "Fan speed (%s)       = %5d [/min]\n" \
                    "${fan_name}" "${fan_speed}"
            fi
        done
        if [ -z "${have_any_fan}" ]; then
            printf "Fan speed              = (not available)\n"
        fi
    fi
    echo
fi # show_temp

if [ "$show_all" = "1" ]; then
    # --- show laptop-mode, dirty buffers params
    echo "+++ File System"
    printparm "%-38s = ##%5d##" /proc/sys/vm/laptop_mode
    printparm "%-38s = ##%5d##" /proc/sys/vm/dirty_writeback_centisecs
    printparm "%-38s = ##%5d##" /proc/sys/vm/dirty_expire_centisecs
    printparm "%-38s = ##%5d##" /proc/sys/vm/dirty_ratio
    printparm "%-38s = ##%5d##" /proc/sys/vm/dirty_background_ratio
    printparm "%-38s = ##%5d##" /proc/sys/fs/xfs/age_buffer_centisecs _
    printparm "%-38s = ##%5d##" /proc/sys/fs/xfs/xfssyncd_centisecs _
    printparm "%-38s = ##%5d##" /proc/sys/fs/xfs/xfsbufd_centisecs _
    echo
fi # show_all

if [ "$show_disk" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show disk info form hdparm
    echo "+++ Storage Devices"
    : ${DISK_DEVICES:=${DEFAULT_DISK_DEVICES}}
    for dev in $DISK_DEVICES; do # iterate all devices
        get_disk_dev $dev

        if [ -b /dev/$disk_dev ]; then
            get_disk_state $disk_dev
            check_disk_hdparm_cap $disk_dev
            if [ $? = 0 ]; then
                echo "/dev/$disk_dev:"

                if [ -n "$disk_id" ]; then
                    echo "  Disk ID   = $disk_id"
                fi

                echo -n "  Model     = "
                echo_disk_model $disk_dev

                echo -n "  Firmware  = "
                echo_disk_firmware $disk_dev

                get_disk_apm_level $disk_dev
                apm=$?
                echo -n "  APM Level = "
                case $apm in
                    0|255) echo "none/disabled" ;;
                    *)     echo $apm ;;
                esac

                echo "  Status    = $disk_state"

                get_disk_trim_capability $disk_dev
                trim=$?
                case $trim in
                    0) echo "  TRIM      = not supported" ;;
                    1) echo "  TRIM      = supported" ;;
                esac

                if [ -f /sys/block/$disk_dev/queue/scheduler ]; then
                    sched="$(cat /sys/block/$disk_dev/queue/scheduler 2> /dev/null | sed -r 's/.*\[(.*)\].*/\1/')"
                    if [ "$sched" = "none" ] && [ -d /sys/block/$disk_dev/mq ]; then
                        sched="blk-mq"
                    fi
                    printf "  Scheduler = %s\n" "$sched"
                fi

                ddev=/sys/block/$disk_dev/device/power
                if [ -f $ddev/control ]; then
                    echo
                    printsysf "  Runtime PM: control = %s, " $ddev/control
                    printsysf "autosuspend_delay = %4s\n"    $ddev/autosuspend_delay_ms
                fi

                if cmd_exists $SMARTCTL ; then
                    # --- show SMART data
                    echo
                    echo "  SMART info:"
                    $SMARTCTL -A /dev/$disk_dev | grep -v '<==' | \
                      awk -F ' ' '$2 ~ /Power_Cycle_Count|Start_Stop_Count|Load_Cycle_Count|Reallocated_Sector_Ct/ \
                                        { printf "    %3d %-25s = %8d \n", $1, $2, $10 } ; \
                                  $2 ~ /Used_Rsvd_Blk_Cnt_Chip|Used_Rsvd_Blk_Cnt_Tot|Unused_Rsvd_Blk_Cnt_Tot/ \
                                        { printf "    %3d %-25s = %8d \n", $1, $2, $10 } ; \
                                  $2 ~ /Power_On_Hours/ \
                                        { printf "    %3d %-25s = %8d %s\n", $1, $2, $10, "[h]" } ; \
                                  $2 ~ /Temperature_Celsius/ \
                                        { printf "    %3d %-25s = %8d %s %s %s %s\n", $1, $2, $10, $11, $12, $13, "[°C]" } ; \
                                  $2 ~ /Airflow_Temperature_Cel/ \
                                        { printf "    %3d %-25s = %8d %s\n", $1, $2, $10, "[°C]" } ; \
                                  $2 ~ /G-Sense_Error_Rate/ \
                                        { printf "    %3d %-25s = %8d \n", $1, $2, $10 } ; \
                                  $2 ~ /Host_Writes/ \
                                        { printf "    %3d %-25s = %8.3f %s\n", $1, $2, $10 / 32768.0, "[TB]" } ; \
                                  $2 ~ /Total_LBAs_Written/ \
                                        { printf "    %3d %-25s = %8.3f %s\n", $1, $2, $10 / 2147483648.0, "[TB]" } ; \
                                  $2 ~ /NAND_Writes_1GiB/ \
                                        { printf "    %3d %-25s = %8d %s\n", $1, $2, $10, "[GB]" } ; \
                                  $2 ~ /Available_Reservd_Space|Media_Wearout_Indicator|Wear_Leveling_Count/ \
                                        { printf "    %3d %-25s = %8d %s\n", $1, $2, $4, "[%]" }'
                fi
                echo

                # restore standby state
                [ "$disk_state" = "standby" ] && spindown_disk $disk_dev
            fi
        fi
    done
    echo

    # --- show sata alpm mode
    echo "+++ AHCI Link Power Management (ALPM)"
    if stat -t /sys/class/scsi_host/host*/link_power_management_policy > /dev/null 2>&1; then
        for i in /sys/class/scsi_host/host* ; do
            printparm "%-56s = ##%s##" $i/link_power_management_policy _
        done
    else
        echo "No AHCI-enabled host controller detected."
    fi
    echo

    # --- show ahci runtime pm
    if stat -t ${AHCID}/power > /dev/null 2>&1; then
        echo "+++ AHCI Host Controller Runtime Power Management"
        for dev in ${AHCID}/power ; do
            printparm "%-40s = ##%s##" $dev/control
        done
        echo
    fi

    # -- show docks
    cnt=0
    for dock in $DOCKGLOB; do
        [ ! -d $dock ] && break # no dock/bay detected

        # dock/bay detected, print header
        [ $cnt -eq 0 ] && echo "+++ Docks and Device Bays"
        cnt=$((cnt+1))

        # get dock type
        { read -r dock_type < $dock/type; } 2>/dev/null

        # get dock state
        if check_is_docked; then
            # docked
            case $dock_type in
                ata_bay)      dock_state="drive present" ;;
                battery_bay)  dock_state="battery present" ;;
                dock_station) dock_state="docked" ;;

                *)  dock_state="docked"
                    dock_type="unknown"
                    ;;
            esac
        else
            # not docked
            case $dock_type in
                ata_bay)      dock_state="no drive (or powered off)" ;;
                battery_bay)  dock_state="no battery " ;;
                dock_station) dock_state="undocked" ;;

                *)  dock_state="undocked"
                    dock_type="unknown"
                    ;;
            esac
        fi

        # print dock data
        printf "%s: %-13s = %s\n" "$dock" "$dock_type" "$dock_state"
    done
    [ $cnt -gt 0 ] && echo
fi # show_disk

if [ "$show_all" = "1" ]; then
    # --- show pcie aspm state
    echo "+++ PCIe Active State Power Management"
    if [ -f $ASPM ]; then
        pol=$(cat $ASPM 2> /dev/null | sed -r 's/.*\[(.*)\].*/\1/')
        { printf '%s' "$pol" > $ASPM; } 2> /dev/null
        if [ $? = 0 ]; then
            echo "$ASPM = $pol"
        else
            echo "$ASPM = $pol (using bios preferences)"
        fi
    else
        echo "$ASPM = (not available)"
    fi
    echo
fi # show_all

if [ "$show_graf" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show i915 power mgmt
    for card in $I915D; do
        if [ -d $card ]; then
            echo "+++ Intel Graphics"
            printparm_i915 $card/powersave
            printparm_i915 $card/enable_rc6 $card/i915_enable_rc6
            printparm_i915 $card/enable_dc
            printparm_i915 $card/enable_fbc $card/i915_enable_fbc
            printparm_i915 $card/enable_psr "" 1
            printparm_i915 $card/lvds_downclock
            printparm_i915 $card/modeset
            printparm_i915 $card/semaphores
            echo
        fi
    done

    # --- show radeon power profile or dpm state
    if [ -d $RADD ]; then
        for card in /sys/class/drm/card[0-9]/device ; do
            if [ -f $card/power_dpm_state ] && [ -f $card/power_dpm_force_performance_level ]; then
                # Use new radeon dpm state
                echo "+++ Radeon Graphics"
                printparm "%-25s = ##%s##" $card/power_dpm_state
                printparm "%-25s = ##%s##" $card/power_dpm_force_performance_level
                echo
                break

            elif [ -f $card/power_method ] && [ -f $card/power_profile ]; then
                # Use old radeon power profile
                echo "+++ Radeon Graphics"
                printparm "%-25s = ##%s##" $card/power_method
                printparm "%-25s = ##%s##" $card/power_profile
                echo
                break
            fi
        done
    fi
fi # show_graf

if [ "$show_rfkill" = "1" ] || [ "$show_all" = "1" ]; then
    echo "+++ Wireless"
    # --- show rfkill state
    for i in bluetooth wifi wwan; do
        get_devc $i
        get_devs $i
        echo_device_state $i $devs
    done
    echo

    ifshown=0

    # --- show bluetooth
    get_bluetooth_ifaces
    for iface in $bifaces; do
        if [ -n "$iface" ]; then
            ifshown=1

            # get bluetooth driver
            get_bluetooth_driver $iface
            printf "%-30s: bluetooth, " "$iface($bluetoothdrv)"
            if bluetooth_in_use $iface; then
                echo "connected"
            else
                echo "not connected"
            fi
        fi
    done

    # --- show wifi data
    get_wifi_ifaces
    for iface in $wifaces; do
        if [ -n "$iface" ]; then
            ifshown=1

            # get wifi power mgmt state
            wifipm=""
            if [ "$X_DONT_USE_IW" != "1" ] && cmd_exists $IW; then
                # try with iw first
                wifipm=$($IW dev $iface get power_save 2> /dev/null | \
                    grep "Power save" | \
                    sed -r 's/.*Power save: (on|off).*/\1/')
            fi
            if cmd_exists $IWC; then
                if [ -z "$wifipm" ]; then
                    # iw did not succeed or iw not installed -> try with iwconfig
                    wifipm=$($IWC $iface 2> /dev/null | \
                        grep "Power Management" | \
                        sed -r 's/.*Power Management:(on|off).*/\1/')
                fi
            fi

            # get wifi driver
            get_wifi_driver $iface
            printf "%-30s: wifi, " "$iface($wifidrv)"
            if wireless_in_use $iface; then
                printf "connected, "
            else
                printf "not connected, "
            fi
            printf "power management = "
            case $wifipm in
                on|off) printf "$wifipm" ;;
                *)      printf "unknown" ;;
            esac
            printf "\n"
        fi
    done

    # --- show wwan data
    get_wwan_ifaces
    for iface in $wanifaces; do
        if [ -n "$iface" ]; then
            ifshown=1

            # get wwan driver
            get_wwan_driver $iface

            printf "%-30s: wwan, " "$iface($wwandrv)"
            if wireless_in_use $iface; then
                printf "connected"
            else
                printf "not connected"
            fi
            printf "\n"
        fi
    done
    [ "$ifshown" = "1" ] && echo

fi # show_rfkill

if [ "$show_all" = "1" ]; then
    # --- show sound power mode
    echo "+++ Audio"
    if [ -d /sys/module/snd_hda_intel ]; then
        printparm "%-58s = ##%s##" /sys/module/snd_hda_intel/parameters/power_save
        printparm "%-58s = ##%s##" /sys/module/snd_hda_intel/parameters/power_save_controller
    fi
    if [ -d /sys/module/snd_ac97_codec ]; then
        printparm "%s = ##%s##" /sys/module/snd_ac97_codec/parameters/power_save
    fi
    echo
fi # show_all

if [ "$show_pcie" = "1" ] || [ "$show_all" = "1" ]; then
    # -- show runtime pm
    echo "+++ Runtime Power Management"
    echo "Device blacklist = ${RUNTIME_PM_BLACKLIST:=(not configured)}"
    pmdbl="${RUNTIME_PM_DRIVER_BLACKLIST-${DEFAULT_PM_DRIVER_BLACKLIST} (default)}"
    echo "Driver blacklist = ${pmdbl:-(disabled)}"
    echo

    if cmd_exists $TLPPCI; then
        $TLPPCI
        [ $? -eq 4 ] && no_runtimepm=1
    else
        echo "Error: missing subcommand $TLPPCI." 1>&2
    fi
    echo

fi # show_pcie

if [ "$show_usb" = "1" ] || [ "$show_all" = "1" ]; then
    # -- show usb autosuspend
    echo "+++ USB"
    if [ "$USB_AUTOSUSPEND" = "1" ]; then
        echo "Autosuspend         = enabled"
    else
        echo "Autosuspend         = disabled"
    fi
    echo "Device whitelist    = ${USB_WHITELIST:=(not configured)}"
    echo "Device blacklist    = ${USB_BLACKLIST:=(not configured)}"
    if [ "${USB_BLACKLIST_BTUSB:-0}" = "1" ]; then
        echo "Bluetooth blacklist = enabled"
    else
        echo "Bluetooth blacklist = disabled"
    fi
    if [ "${USB_BLACKLIST_PHONE:-0}" = "1" ]; then
        echo "Phone blacklist     = enabled"
    else
        echo "Phone blacklist     = disabled"
    fi
    if [ "${USB_BLACKLIST_WWAN:-1}" = "1" ]; then
        echo "WWAN blacklist      = enabled"
    else
        echo "WWAN blacklist      = disabled"
    fi
    if [ -n "$USB_DRIVER_BLACKLIST" ] && [ "$USB_DRIVER_BLACKLIST" != "usbhid" ]; then
        echo "Notice: USB_DRIVER_BLACKLIST is no longer supported, use USB_BLACKLIST."
    fi
    echo

    if cmd_exists $TLPUSB; then
        $TLPUSB
        [ $? -eq 4 ] && no_runtimepm=1
    else
        echo "Error: missing subcommand $TLPUSB." 1>&2
    fi
    echo

fi # show_usb

if [ "$show_bat" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show battery info & charge thresholds
    bcnt=0
    efsum=0
    ensum=0

    # --- show availability of ThinkPad battery features
    if is_thinkpad; then
        echo "+++ ThinkPad Battery Features"
        echo -n "tp-smapi   = "
        case $tpsmapi in
            0)   echo "active" ;;
            2)   echo "inactive (kernel module 'tp_smapi' load error)" ;;
            127) echo "inactive (kernel module 'tp_smapi' not installed)" ;;
            255) echo "inactive (unsupported hardware)" ;;
            *)   echo "unknown status"
        esac

        echo -n "tpacpi-bat = "
        case $tpacpi in
            0)   echo "active" ;;
            2)   echo "inactive (kernel module 'acpi_call' load error)" ;;
            4)   echo "inactive (disabled by user configuration)" ;;
            127) echo "inactive (kernel module 'acpi_call' not installed)" ;;
            255) echo "inactive (unsupported hardware)" ;;
        esac
        echo
    fi

    if [ $tpsmapi -eq 0 ]; then
        # it's a ThinkPad with tp-smapi

        for batd in $SMAPIDIR/BAT[01]; do
            if [ -d $batd ]; then
                batt=${batd##/*/}

                if check_tp_battery $batt; then # battery is present
                    case $bat_idx in
                        1) echo "+++ ThinkPad Battery Status: $batt (Main / Internal)" ;;
                        2) echo "+++ ThinkPad Battery Status: $batt (Ultrabay / Slice / Replaceable)" ;;
                        0) echo "+++ ThinkPad Battery Status: $batt" ;;
                    esac

                    printparm "%-59s = ##%s##" $batd/manufacturer
                    printparm "%-59s = ##%s##" $batd/model
                    printparm "%-59s = ##%s##" $batd/manufacture_date
                    printparm "%-59s = ##%s##" $batd/first_use_date
                    printparm "%-59s = ##%6d##" $batd/cycle_count

                    if [ -f $batd/temperature ]; then
                        perl -e 'printf ("%-59s = %6d [°C]\n", "'$batd/temperature'", '$(catsysfd $batd/temperature 0)' / 1000.0);'
                    fi

                    printparm "%-59s = ##%6d## [mWh]" $batd/design_capacity
                    printparm "%-59s = ##%6d## [mWh]" $batd/last_full_capacity
                    printparm "%-59s = ##%6d## [mWh]" $batd/remaining_capacity
                    printparm "%-59s = ##%6d## [%%]" $batd/remaining_percent
                    printparm "%-59s = ##%6s## [min]" $batd/remaining_running_time_now
                    printparm "%-59s = ##%6s## [min]" $batd/remaining_charging_time
                    printparm "%-59s = ##%6d## [mW]" $batd/power_now
                    printparm "%-59s = ##%6d## [mW]" $batd/power_avg
                    print_tp_batstate $batd/state
                    echo
                    if [ $show_verbose -eq 1 ]; then
                        printparm "%-59s = ##%6s## [mV]" $batd/design_voltage
                        printparm "%-59s = ##%6s## [mV]" $batd/voltage
                        printparm "%-59s = ##%6s## [mV]" $batd/group0_voltage
                        printparm "%-59s = ##%6s## [mV]" $batd/group1_voltage
                        printparm "%-59s = ##%6s## [mV]" $batd/group2_voltage
                        printparm "%-59s = ##%6s## [mV]" $batd/group3_voltage
                        echo
                    fi

                    if [ $tpacpi -eq 0 ]; then
                        # --- show ThinkPad charge thresholds via tpacpi-bat
                        print_tpacpi_thresholds $batt $bat_idx
                    else
                        # show thresholds via tp-smapi
                        printparm "%-59s = ##%6d## [%%]" $batd/start_charge_thresh
                        printparm "%-59s = ##%6d## [%%]" $batd/stop_charge_thresh
                        printparm "%-59s = ##%6d##" $batd/force_discharge
                    fi
                    echo

                    # store values for charge / capacity calculation below
                    ed=$(catsysfd $batd/design_capacity 0)
                    ef=$(catsysfd $batd/last_full_capacity 0)
                    en=$(catsysfd $batd/remaining_capacity 0)
                    efsum=$(($efsum + $ef))
                    ensum=$(($ensum + $en))

                    # show charge + capacity
                    lcnt=0
                    if [ $ef -ne 0 ]; then
                        perl -e 'printf ("%-59s = %6.1f [%%]\n", "Charge",   100.0 * '$en' / '$ef');'
                        lcnt=$(($lcnt+1))
                    fi
                    if [ $ed -ne 0 ]; then
                        perl -e 'printf ("%-59s = %6.1f [%%]\n", "Capacity", 100.0 * '$ef' / '$ed');'
                        lcnt=$(($lcnt+1))
                    fi
                    [ $lcnt -gt 0 ] && echo

                    bcnt=$(($bcnt+1))
                fi
            fi
        done
    elif [ -d $ACPIBATDIR ]; then
        # --- show ACPI data

        for batd in $ACPIBATDIR/*; do
            batt=${batd##/*/}
            tpbat=0

            if check_tp_battery $batt; then
                # ThinkPad battery is present
                tpbat=1

                if [ $tpacpi -eq 0 ]; then
                    # it's a ThinkPad with tpacpi-bat only
                    case $bat_idx in
                        1) echo "+++ ThinkPad Battery Status: $batt (Main / Internal)" ;;
                        2) echo "+++ ThinkPad Battery Status: $batt (Ultrabay / Slice / Replaceable)" ;;
                        0) echo "+++ ThinkPad Battery Status: $batt" ;;
                    esac
                else
                   # it's a ThinkPad with neither tp-smapi nor tpacpi-bat
                    echo "+++ Battery Status"
                fi
            elif [ -d $batd ] \
                 && [ "$(cat $batd/type 2> /dev/null)" = "Battery" ] \
                 && [ "$(cat $batd/present 2> /dev/null )" = "1" ]; then
                    # it's some other laptop model or brand
                    echo "+++ Battery Status"
            else
                batt="" # power supply is not a battery
            fi

            if [ -n "$batt" ]; then
                printparm "%-59s = ##%s##" $batd/manufacturer
                printparm "%-59s = ##%s##" $batd/model_name

                cc=$(cat $batd/cycle_count 2> /dev/null)
                if [ $? -eq 0 ] && [ -n "$cc" ] && [ $cc -gt 0 ]; then
                    printf "%-59s = %6d\n" "$batd/cycle_count" "$cc"
                else
                    printf "%-59s = (not supported)\n" "$batd/cycle_count"
                fi

                if [ -f $batd/energy_full ]; then
                    printparm "%-59s = ##%6d## [mWh]" $batd/energy_full_design "" 000
                    printparm "%-59s = ##%6d## [mWh]" $batd/energy_full "" 000
                    printparm "%-59s = ##%6d## [mWh]" $batd/energy_now "" 000
                    printparm "%-59s = ##%6d## [mW]" $batd/power_now "" 000

                    # store values for charge / capacity calculation below
                    ed=$(catsysfd $batd/energy_full_design 0)
                    ef=$(catsysfd $batd/energy_full 0)
                    en=$(catsysfd $batd/energy_now 0)
                    efsum=$(($efsum + $ef))
                    ensum=$(($ensum + $en))

                elif [ -f $batd/charge_full ]; then
                    printparm "%-59s = ##%6d## [mAh]" $batd/charge_full_design "" 000
                    printparm "%-59s = ##%6d## [mAh]" $batd/charge_full "" 000
                    printparm "%-59s = ##%6d## [mAh]" $batd/charge_now "" 000
                    printparm "%-59s = ##%6d## [mA]" $batd/current_now "" 000

                    # store values for charge / capacity calculation below
                    ed=$(catsysfd $batd/charge_full_design 0)
                    ef=$(catsysfd $batd/charge_full 0)
                    en=$(catsysfd $batd/charge_now 0)
                    efsum=$(($efsum + $ef))
                    ensum=$(($ensum + $en))

                else
                    ed=0
                    ef=0
                    en=0

                fi
                if [ $tpbat -eq 1 ]; then
                    print_tp_batstate $batd/status
                else
                    printparm "%-59s = ##%s##" $batd/status
                fi
                echo

                if [ $show_verbose -eq 1 ]; then
                    printparm "%-59s = ##%6s## [mV]" $batd/voltage_min_design "" 000
                    printparm "%-59s = ##%6s## [mV]" $batd/voltage_now "" 000
                    echo
                fi

                if [ $tpacpi -eq 0 ]; then
                    # --- show ThinkPad charge thresholds via tpacpi-bat
                    print_tpacpi_thresholds $batt $bat_idx
                    echo
                fi # if $tpcacpi

                # show charge + capacity
                lcnt=0
                if [ $ef -ne 0 ]; then
                    perl -e 'printf ("%-59s = %6.1f [%%]\n", "Charge",   100.0 * '$en' / '$ef');'
                    lcnt=$(($lcnt+1))
                fi
                if [ $ed -ne 0 ]; then
                    perl -e 'printf ("%-59s = %6.1f [%%]\n", "Capacity", 100.0 * '$ef' / '$ed');'
                    lcnt=$(($lcnt+1))
                fi
                [ $lcnt -gt 0 ] && echo

                bcnt=$(($bcnt+1))
            fi # if $batt
        done # $batd

    fi # if /sys/class/power_supply

    if [ $bcnt -eq 0 ]; then
        # no battery detected
        printf "+++ Battery Status\n"
        printf "No batteries detected.\n\n"
    elif [ $bcnt -gt 1 ] && [ $efsum -ne 0 ]; then
        # more than one battery detected --> show charge total
        perl -e 'printf ("%-59s = %6.1f [%%]\n", "+++ Charge total",   100.0 * '$ensum' / '$efsum');'
        echo
    fi

fi # show_bat

if [ "$show_warn" = "1" ] || [ "$show_disk" = "1" ] || [ "$show_all" = "1" ]; then
    # --- show warnings
    # ata errors (possibly) caused by SATA_LINKPWR_ON_AC/BAT != max_performance
    ecnt=$( check_ata_errors )
    if [ $ecnt -ne 0 ]; then
        echo "+++ Warnings"
        printf "* Kernel log shows ata errors (%d) possibly caused by the configuration\n" $ecnt
        printf "  SATA_LINKPWR_ON_AC/BAT=min_power or medium_power.\n"
        printf "  Consider using medium_power or max_performance instead.\n"
        printf "  See the FAQ: http://linrunner.de/en/tlp/docs/tlp-faq.html#warnings\n"
        printf "  Details:\n"
        dmesg | egrep -A 5 "${RE_ATA_ERROR}"
        echo
    elif [ "$show_warn" = "1" ]; then
        echo "No warnings detected."
        echo ""
    fi

fi # show_warn

if [ "$show_all" = "1" ]; then
    # -- show suggestions
    suout=""

    if [ "$no_runtimepm" = "1" ]; then
        suout="${suout}Reconfigure your Linux kernel with PM_RUNTIME=y to reduce your laptop's power consumption.\n"
    fi

    if is_thinkpad; then
        # add ThinkPad specific suggestions -- $tpmodel preset by check_thinkpad()
        if supports_tpsmapi_only; then
            # tp-smapi only capable models
            [ $tpsmapi -eq 127 ] && suout="${suout}Install tp-smapi kernel modules for ThinkPad battery features\n"

        elif supports_tpacpi_only; then
            # tpacpi-bat only capable models
            [ $tpacpi -eq 127 ] && suout="${suout}Install acpi-call kernel module for ThinkPad battery features\n"

        elif supports_tpsmapi_and_tpacpi; then
            # tp-smapi and tpacpi-bat capable models
            [ $tpsmapi -eq 127 ] && suout="${suout}Install tp-smapi kernel modules for ThinkPad battery features\n"
            [ $tpacpi -eq 127 ]  && suout="${suout}Install acpi-call kernel module for ThinkPad battery features\n"

        elif supports_no_tp_bat_funcs; then
            : # models that are neither tp_smapi nor tpacpi-bat capable

        else
            # all others assumed tp-smapi capable ...
            [ $tpsmapi -eq 127 ] && suout="${suout}Install tp-smapi kernel modules for ThinkPad battery features\n"

        fi
    fi # if ThinkPad

    # add other suggestions
    cmd_exists ethtool || suout="${suout}Install ethtool to disable Wake On LAN (WOL)\n"
    cmd_exists smartctl || suout="${suout}Install smartmontools for disk drive health info\n"

    if [ -n "$suout" ]; then
        echo "+++ Suggestions"
        printf "$suout" | sed -r 's/^/\* /'
        echo
    fi

fi # show_all

if [ "$show_pev" = "1" ]; then
    # --- show udev power_supply events

    # check for udevadm
    if cmd_exists $UDEVADM; then
        echo "+++ Monitor power supply events -- cancel with ^C"
        echo
        $UDEVADM monitor --udev --property --subsystem-match=power_supply
    fi
fi # show_pev

if [ "$show_psup" = "1" ]; then
    # --- show power_supply diagnostic
    echo "+++ Power supply diagnostic"
    for ps in /sys/class/power_supply/*; do
        grep -s '.*' $ps/type $ps/online $ps/present $ps/device/path
    done
fi # show_sup

if [ "$show_trace" = "1" ]; then
    # --- show debug log

    # check for systemd journal
    jdone=0
    if cmd_exists $JOURNALCTL; then
        # retrieve trace output from journal
        $JOURNALCTL -p debug --no-pager SYSLOG_IDENTIFIER=tlp 2> /dev/null
        # check result -- rc=1 if journald has no data available
        [ $? -eq 0 ] && jdone=1
    fi

    if [ "$jdone" = "0"  ]; then
        # no journald data available --> retrieve trace output from logfile
        if [ -f $DEBUGLOG ]; then
            grep "tlp\[" $DEBUGLOG
        else
            echo "Error: $DEBUGLOG does not exist." 1>&2
            echo 1>&2
            echo "Solution: create an rsyslog conffile /etc/rsyslog.d/90-debug.conf with the following contents" 1>&2
            echo " *.=debug;\\" 1>&2
            echo " mail,authpriv,cron.none;\\" 1>&2
            echo " local0,local1,local3,local4,\\" 1>&2
            echo " local5,local6,local7.none    -/var/log/debug" 1>&2
            echo "and restart the rsyslog daemon." 1>&2
            echo 1>&2
        fi
    fi
fi # show_trace

exit 0
