summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2018-06-01 02:13:37 (EDT)
committer P. J. McDermott <pj@pehjota.net>2018-06-03 23:15:22 (EDT)
commit2a23d06442c804f979bd57146a486b943b4df138 (patch)
treec5578b0c701f038ca830b83ceadc70add0f1d57b
parent6efb7ef317faebd481f96d9b2b681314cf753f63 (diff)
downloadhomerc-2a23d06442c804f979bd57146a486b943b4df138.zip
homerc-2a23d06442c804f979bd57146a486b943b4df138.tar.gz
homerc-2a23d06442c804f979bd57146a486b943b4df138.tar.bz2
bin/rc: New script
-rw-r--r--.gitignore.d/homerc2
-rwxr-xr-xbin/rc200
2 files changed, 202 insertions, 0 deletions
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} <session-type>\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 "${@}"