diff --git a/xrsbs b/xrsbs new file mode 100755 index 0000000..69a7f96 --- /dev/null +++ b/xrsbs @@ -0,0 +1,106 @@ +#!/bin/bash + +USAGE=" +USAGE: xrsb-sched [] [] + + action A comma or space separated list of actions to associate with the + update signal. + + when The integer number of milliseconds to wait before sending the + update signal, or one of the following values: + - m to send the update signal at the top of the next minute + - h to send the update signal at the top of the next hour + - d to send the update signal at the top of the next day + If not present, the update signal will be sent immediately. + + repeat If present, the update signal will be sent repeatedly according + to . + +EXAMPLES: + + If the daemon interprets the actions 'vol' and 'bl' to mean update the + volume and backlight statuses, respectively, send a signal to + immediately update both of those statuses. + + xsrb-sched 'vol,bl' + + If the daemon interprets the actions 'cpu' and 'mem' to mean update the + cpu and memory usage statuses, respectively, send a signal to update + both of those statuses every 5 seconds. + + xsrb-sched 'cpu,mem' 5000 1 + + If the daemon interprets the actions 'bat' and 'dt' to mean update the + battery and date/time statuses, respectively, send a signal to update + both of those statuses at the top of every minute. + + xsrb-sched 'bat,dt' m true +" +DAEMON=xrsbd +ACTION_DIR=/tmp/xrsb-action/ + +# Convert integer milliseconds to floating point seconds +ms_to_s () { + printf '%.3f' "${1}e-3" +} + +# Validate the arguments +if [[ "$#" -lt 1 || "$#" -gt 3 ]]; then + printf '%s' "${USAGE}" 1>&2 + exit 128 +fi + +IFS=', ' read -r -a actions <<< "$1" +when="${2:-0}" +repeat="$3" + +if [[ ! "${when}" =~ ^[0-9]+|[mhd]$ ]]; then + printf 'Invalid argument : %s\n' "${when}" 1>&2 + exit 128 +fi + +# Get the daemon PID so we can send the signal to it later. Getting the PID once +# here is more efficient than getting it each time in the while loop, but if the +# daemon is restarted and the PID changes, all subsequent updates will fail. +daemon_pid="$(pgrep --newest --exact "${DAEMON}")" +if [[ -z "${daemon_pid}" ]]; then + printf 'The daemon %s is not running\n' "${DAEMON}" 1>&2 + exit 1 +fi + +# Send the signal if this is the first run or if repeat is on +first_run=1 +while [[ "${first_run}" -eq 1 || -n "${repeat}" ]]; do + first_run=0 + + # Sleep until it's time to send the signal + if [[ "${when}" != '0' ]]; then + if [[ "${when}" =~ ^[0-9]+$ ]]; then + sleep "$(ms_to_s "${when}")" + else + case "${when}" in + m) + sleep $((60 - $(date +%S))) + ;; + h) + readarray -t ms < <(date +'%M%n%S') + sleep $((3600 - ms[0] * 60 - ms[1])) + ;; + d) + readarray -t hms < <(date +'%H%n%M%n%S') + ##sleep $(((24 - hms[0]) * 3600 - hms[1] * 60 - hms[2])) + printf '%d\n' $(((24 - hms[0]) * 3600 - hms[1] * 60 - hms[2])) + ;; + esac + fi + fi + + # Create the signal data and send the signal to the daemon + if [[ "$(ps --no-headers -o '%c' -q "${daemon_pid}")" != "${DAEMON}" ]]; then + printf 'The daemon %s is not running\n' "${DAEMON}" 1>&2 + exit 1 + fi + for action in "${actions[@]}"; do touch "${ACTION_DIR}/${action}"; done + kill -SIGUSR1 "${daemon_pid}" +done +