#!/bin/sh # # hwmon -- Panel applet to monitor Linux hwmon (temp, fan, and power) sensors # # Copyright (C) 2018 Patrick "P. J." McDermott # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. set -eu cr=0 debug=0 err() { local fmt="${1}" shift 1 printf "Error: ${fmt}\n" "${@}" 1>&2 return 0 } dbg() { local fmt="${1}" shift 1 case "${debug}" in '1') printf "DEBUG: ${fmt}\n" "${@}" 1>&2 esac return 0 } lookup_chips() { local hwmon_dir= local hwmon= local name= for hwmon_dir in /sys/class/hwmon/hwmon*; do hwmon="${hwmon_dir#/sys/class/hwmon/}" if [ -f "${hwmon_dir}/name" ]; then read -r name <"${hwmon_dir}/name" elif [ -f "${hwmon_dir}/device/name" ]; then read -r name <"${hwmon_dir}/device/name" else return 1 fi printf '%s %s\n' "${hwmon}" "${name}" dbg 'Chip %s = %s' "${name}" "${hwmon}" done return 0 } lookup_chip() { local chip="${1}" local chips="${2}" shift 2 local hwmon= local name= while read -r hwmon name; do case "${name}" in "${chip}") printf '%s' "${hwmon}" return 0 esac done <<-EOF ${chips} EOF return 1 } read_value() { local hwmon="${1}" local element="${2}" shift 2 local hwmon_dir= local value= hwmon_dir="/sys/class/hwmon/${hwmon}" if [ -f "${hwmon_dir}/${element}_input" ]; then read -r value <"${hwmon_dir}/${element}_input" elif [ -f "${hwmon_dir}/device/${element}_input" ]; then read -r value <"${hwmon_dir}/device/${element}_input" else return 1 fi printf '%s' "${value}" return 0 } format_temp() { local hwmon="${1}" local element="${2}" shift 2 local value= value="$(read_value "${hwmon}" "${element}")" || return 1 printf '%d C' "${value%???}" return 0 } format_fan() { local hwmon="${1}" local element="${2}" shift 2 local value= value="$(read_value "${hwmon}" "${element}")" || return 1 printf '%d RPM' "${value}" return 0 } format_power() { local hwmon="${1}" local element="${2}" shift 2 local value= value="$(read_value "${hwmon}" "${element}")" || return 1 printf '%d W' "${value%??????}" return 0 } print_sensor() { local indent=${1} local label="${2}" local len=${3} local chip="${4}" local chips="${5}" local element="${6}" shift 6 local hwmon= local value= local i= if ! hwmon="$(lookup_chip "${chip}" "${chips}")"; then err 'Unknown chip "%s"' "${chip}" return 1 fi case "${element}" in 'temp'*) value="$(format_temp "${hwmon}" "${element}")" || \ return 1 ;; 'fan'*) value="$(format_fan "${hwmon}" "${element}")" || \ return 1 ;; 'power'*) value="$(format_power "${hwmon}" "${element}")" || \ return 1 ;; *) err 'Unsupported type of element "%s"' "${element}" return 1 ;; esac i=0 while [ ${i} -lt ${indent} ]; do printf ' ' i=$((${i} + 1)) done case "${label}" in ?*) printf '%s: ' "${label}" i=${#label} while [ ${i} -lt ${len} ]; do printf ' ' i=$((${i} + 1)) done esac case "${cr}" in 1) printf '%s\r' "${value}";; 0) printf '%s\n' "${value}";; esac return 0 } usage() { printf 'Usage: %s [] %s [%s ...]\n' "${0}" \ '