summaryrefslogtreecommitdiffstats
path: root/bin/rc
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2018-06-01 13:36:36 (EDT)
committer P. J. McDermott <pj@pehjota.net>2018-06-03 23:17:34 (EDT)
commit03b4f6ebd3c9e1f1bb6edb09bce67071417ed526 (patch)
tree3b00f2675d14c428db9c15f090e834160f2d24eb /bin/rc
parent2a23d06442c804f979bd57146a486b943b4df138 (diff)
downloadhomerc-03b4f6ebd3c9e1f1bb6edb09bce67071417ed526.zip
homerc-03b4f6ebd3c9e1f1bb6edb09bce67071417ed526.tar.gz
homerc-03b4f6ebd3c9e1f1bb6edb09bce67071417ed526.tar.bz2
bin/rc: Daemonize, add status cmd, and run svcs
And pass old and new session type lists to services instead of list of added or removed session type and ancestor types.
Diffstat (limited to 'bin/rc')
-rwxr-xr-xbin/rc249
1 files changed, 183 insertions, 66 deletions
diff --git a/bin/rc b/bin/rc
index 1b6c1cd..277c2aa 100755
--- a/bin/rc
+++ b/bin/rc
@@ -2,12 +2,14 @@
set -eu
-RC_MAGIC='~/rc'
+MAGIC='~/rc'
progname=
rc_fifo=
+res_fifo=
+sessions=','
-error()
+info()
{
local fmt="${1}"
shift 1
@@ -17,6 +19,16 @@ error()
return 0
}
+error()
+{
+ local fmt="${1}"
+ shift 1
+
+ printf "%s: Error: ${fmt}\n" "${progname}" "${@}" 1>&2
+
+ return 0
+}
+
valid_session_type()
{
local session_type="${1}"
@@ -28,59 +40,97 @@ valid_session_type()
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()
+run_services()
{
- 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
+ local old_sessions="${1}"
+ local new_sessions="${1}"
+ shift 1
+ local service_script=
- 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%:*}"
+ for service_script in "${XDG_CACHE_HOME:-${HOME}/.cache}/homerc/"*; do
+ "$(dirname ${0})/svc" "${service_script##*/}" \
+ "${old_sessions};${new_sessions}"
done
-
- diff="${diff%,}"
}
beg_session()
{
local session_type="${1}"
shift 1
+ local s_type=
+ local add=
+ local new_sessions=
+ local old_sessions=
+
+ s_type="$(printf '%s' "${session_type}" | tr ':' '_')"
+
+ if eval "[ \${sessions_${s_type}:-0} -eq 0 ]"; then
+ add=true
+ else
+ add=false
+ fi
+
+ # Increment.
+ eval "sessions_${s_type}=\$((\${sessions_${s_type}:-0} + 1))"
- chg_session "${session_type}" 1 '+'
- return ${?}
+ if ${add}; then
+ new_sessions="${sessions}${session_type},"
+ old_sessions="${sessions}"
+ sessions="${new_sessions}"
+ run_services "${old_sessions}" "${new_sessions}"
+ return ${?}
+ fi
+
+ return 0
}
end_session()
{
local session_type="${1}"
shift 1
+ local s_type=
+ local new_sessions=
+ local old_sessions=
- chg_session "${session_type}" -1 '-'
- return ${?}
+ s_type="$(printf '%s' "${session_type}" | tr ':' '_')"
+
+ if eval "[ \${sessions_${s_type}:-0} -eq 0 ]"; then
+ error 'No running sessions of type %s' "${session_type}"
+ return 1
+ fi
+
+ # Decrement.
+ eval "sessions_${s_type}=\$((\${sessions_${s_type}} - 1))"
+
+ if eval "[ \${sessions_${s_type}} -eq 0 ]"; then
+ eval "unset sessions_${s_type}"
+ new_sessions="${sessions%,${session_type},*}"
+ new_sessions="${new_sessions},${sessions#*,${session_type},}"
+ old_sessions="${sessions}"
+ sessions="${new_sessions}"
+ run_services "${old_sessions}" "${new_sessions}"
+ return ${?}
+ fi
+
+ return 0
+}
+
+list_sessions()
+{
+ local printed=
+ local session=
+
+ printed=false
+ IFS=','
+ for session in ${sessions}; do
+ unset IFS
+ if ${printed}; then
+ printf ', '
+ fi
+ eval "printf '%s (%d)' '${session}' \${sessions_${session}}"
+ printed=true
+ done
+ unset IFS
}
listen()
@@ -91,43 +141,72 @@ listen()
while :; do
if read -r magic cmd arg; then
- case "${magic}" in "${RC_MAGIC}");; *)
+ case "${magic}" in "${MAGIC}");; *)
continue
esac
+ 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
+ ;;
+ 'who')
+ {
+ printf '%s ' "${MAGIC}"
+ list_sessions
+ printf '\n'
+ } 1>"${arg}"
+ ;;
+ 'bye')
+ break
+ ;;
+ *)
+ 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}"
}
+run_daemon()
+{
+ local session_type="${1}"
+ shift 1
+ local piddir=
+
+ exec 0<&- 1>&- 2>&-
+ # TODO:
+ # Disassociate from its process group (usually a shell), to insulate
+ # itself from signals (such as HUP) sent to the process group
+ # Ignore all terminal I/O signals
+
+ piddir="${XDG_CACHE_HOME:-${HOME}/.cache}/homerc"
+ mkdir -p "${piddir}"
+ rm -f "${piddir}/"*
+
+ beg_session "${session_type}"
+ listen
+ rm "${rc_fifo}"
+ rm -f "${piddir}/"*
+
+ return 0
+}
+
start()
{
local session_type="${1}"
shift 1
- if mkfifo "${rc_fifo}" 2>/dev/null; then
- beg_session "${session_type}"
- listen
- rm "${rc_fifo}"
+ if mkfifo -m 0600 "${rc_fifo}" 2>/dev/null; then
+ run_daemon "${session_type}" &
else
# Signal the running rc daemon.
- printf "%s beg %s\n" "${RC_MAGIC}" "${session_type}" \
+ printf "%s beg %s\n" "${MAGIC}" "${session_type}" \
1>"${rc_fifo}"
fi
@@ -139,24 +218,58 @@ 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.
+ if mkfifo -m 0600 "${rc_fifo}" 2>/dev/null; then
+ # Daemonizing 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}" \
+ printf "%s end %s\n" "${MAGIC}" "${session_type}" \
1>"${rc_fifo}"
fi
return 0
}
+status()
+{
+ local magic=
+ local list=
+
+ if mkfifo -m 0600 "${rc_fifo}" 2>/dev/null; then
+ # Daemonizing just to list non-existent sessions makes no sense.
+ error 'No running daemon found'
+ rm "${rc_fifo}"
+ return 1
+ else
+ # Establish response FIFO.
+ if ! mkfifo -m 0600 "${res_fifo}" 2>/dev/null; then
+ error 'Failed to communicate with running daemon'
+ return 1
+ fi
+ # Signal the running rc daemon.
+ printf "%s who %s\n" "${MAGIC}" "${res_fifo}" \
+ 1>"${rc_fifo}"
+ if read -r magic list; then
+ case "${magic}" in "${MAGIC}");; *)
+ continue
+ esac
+ info 'Sessions: %s' "${list}"
+ else
+ error 'Failed to communicate with running daemon'
+ rm "${res_fifo}"
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
usage()
{
printf 'Usage: %s {start|stop} <session-type>\n' "${0}"
+ printf ' or: %s status\n' "${0}"
return 0
}
@@ -180,6 +293,7 @@ main()
progname="${0##*/}"
rc_fifo="/tmp/homercrc-$(id -u)"
+ res_fifo="/tmp/homercres-${$}"
case "${action}" in
'start')
@@ -188,6 +302,9 @@ main()
'stop')
stop "${session_type}"
;;
+ 'status')
+ status
+ ;;
*)
usage 1>&2
return 1