summaryrefslogtreecommitdiffstats
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
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.
-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