From 2a23d06442c804f979bd57146a486b943b4df138 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Fri, 01 Jun 2018 02:13:37 -0400 Subject: bin/rc: New script --- diff --git a/.gitignore.d/homerc b/.gitignore.d/homerc index 89274fe..66206ac 100644 --- a/.gitignore.d/homerc +++ b/.gitignore.d/homerc @@ -4,6 +4,8 @@ # Include relevant files !/.gitignore.d/ !/.gitignore.d/homerc +!/bin/ +!/bin/rc # Exclude swap and backup files *.s[a-w]? diff --git a/bin/rc b/bin/rc new file mode 100755 index 0000000..1b6c1cd --- /dev/null +++ b/bin/rc @@ -0,0 +1,200 @@ +#!/bin/sh + +set -eu + +RC_MAGIC='~/rc' + +progname= +rc_fifo= + +error() +{ + local fmt="${1}" + shift 1 + + printf "%s: ${fmt}\n" "${progname}" "${@}" + + return 0 +} + +valid_session_type() +{ + local session_type="${1}" + shift 1 + + case "${session_type}" in *[!A-Za-z0-9:]* | '' | ':'* | *':') + return 1 + esac + return 0 +} + +# Returns 0 if the session is the first of its type or was last of its type +# TODO: Handle decrement from 0. +inc_session() +{ + local s_type="${1}" + local dir=${2} + shift 2 + local ret= + + ret=1 + + s_type="$(printf '%s' "${s_type}" | tr ':' '_')" + eval "[ \${sessions_${s_type}:-0} -eq 0 ] && ret=0" + eval "sessions_${s_type}=\$((\${sessions_${s_type}:-0} + ${dir}))" + eval "[ \${sessions_${s_type}} -eq 0 ] && ret=0" + + return ${ret} +} + +chg_session() +{ + local session_type="${1}" + local inc_dir=${2} + local diff="${3}" + shift 3 + + while :; do + case "${session_type}" in *:*);; *) break;; esac + if inc_session "${session_type}" ${inc_dir}; then + diff="${diff}${session_type}," + fi + session_type="${session_type%:*}" + done + + diff="${diff%,}" +} + +beg_session() +{ + local session_type="${1}" + shift 1 + + chg_session "${session_type}" 1 '+' + return ${?} +} + +end_session() +{ + local session_type="${1}" + shift 1 + + chg_session "${session_type}" -1 '-' + return ${?} +} + +listen() +{ + local magic= + local cmd= + local arg= + + while :; do + if read -r magic cmd arg; then + case "${magic}" in "${RC_MAGIC}");; *) + continue + esac + fi + case "${cmd}" in + 'beg') + if valid_session_type "${arg}"; then + beg_session "${arg}" + fi + ;; + 'end') + if valid_session_type "${arg}"; then + end_session "${arg}" + fi + ;; + 'bye') + break + ;; + *) + continue + ;; + esac + done 0<"${rc_fifo}" +} + +start() +{ + local session_type="${1}" + shift 1 + + if mkfifo "${rc_fifo}" 2>/dev/null; then + beg_session "${session_type}" + listen + rm "${rc_fifo}" + else + # Signal the running rc daemon. + printf "%s beg %s\n" "${RC_MAGIC}" "${session_type}" \ + 1>"${rc_fifo}" + fi + + return 0 +} + +stop() +{ + local session_type="${1}" + shift 1 + + if mkfifo "${rc_fifo}" 2>/dev/null; then + # Assuming the daemon role just to end a non-existent session + # makes no sense. + error 'No running daemon found' + rm "${rc_fifo}" + return 1 + else + # Signal the running rc daemon. + printf "%s end %s\n" "${RC_MAGIC}" "${session_type}" \ + 1>"${rc_fifo}" + fi + + return 0 +} + +usage() +{ + printf 'Usage: %s {start|stop} \n' "${0}" + + return 0 +} + +main() +{ + local action= + local session_type= + + if [ ${#} -ne 2 ]; then + usage 1>&2 + return 1 + fi + action="${1}" + session_type="${2}" + + if ! valid_session_type; then + error 'Invalid session type' + return 1 + fi + + progname="${0##*/}" + rc_fifo="/tmp/homercrc-$(id -u)" + + case "${action}" in + 'start') + start "${session_type}" + ;; + 'stop') + stop "${session_type}" + ;; + *) + usage 1>&2 + return 1 + ;; + esac + + return 0 +} + +main "${@}" -- cgit v0.9.1