diff --git a/README.md b/README.md index ae78da7..c1b6c56 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,20 @@ absent or invalid, the popup disables itself cleanly while input processing continues. `run.sh` and `bench.sh` accept the same font-file arguments. When `run.sh` is invoked without arguments, it uses the installed DejaVu, Jigmo, or Noto CJK font files from the standard Arch Linux paths. Explicit -font-file arguments replace these defaults. +font-file arguments replace these defaults: + +```sh +./run.sh +./run.sh /path/to/primary.ttf /path/to/fallback.ttc +``` + +`run.sh` remains in the foreground and owns only the daemon and XIM process +that it starts. It waits for that daemon's IPC socket and IBus address file +before reporting success. With `DISPLAY` set it then starts XIM; without a +display it keeps the headless daemon in the foreground and does not start +XIM. A signal or XIM exit stops and reaps the launcher's daemon. The +launcher never replaces an existing daemon: an occupied per-user socket is a +visible startup failure. The IPC socket is placed at `$XDG_RUNTIME_DIR/strans.sock` when `XDG_RUNTIME_DIR` is an absolute path. Otherwise strans uses the per-user diff --git a/bench.sh b/bench.sh index 287a233..67dbcbb 100755 --- a/bench.sh +++ b/bench.sh @@ -2,30 +2,97 @@ set -eu -cd "$(dirname "$0")" +cd "$(dirname "$0")" || exit 1 + +case ${XDG_RUNTIME_DIR-} in +/) ipc=/strans.sock ;; +/*/) ipc=${XDG_RUNTIME_DIR}strans.sock ;; +/*) ipc=${XDG_RUNTIME_DIR}/strans.sock ;; +*) ipc=/tmp/strans.$(id -u) ;; +esac +if test -n "${XDG_CONFIG_HOME-}"; then + busdir=$XDG_CONFIG_HOME/ibus/bus +elif test "${HOME+x}" = x; then + busdir=$HOME/.config/ibus/bus +else + echo "bench.sh: HOME or XDG_CONFIG_HOME is required for IBus discovery" >&2 + exit 1 +fi strans_pid= perf_pid= cleanup() { + status=$? trap - 0 1 2 15 if test -n "$perf_pid"; then - kill -INT "$perf_pid" 2>/dev/null || true - wait "$perf_pid" 2>/dev/null || true + kill -INT "$perf_pid" 2>/dev/null || : + wait "$perf_pid" 2>/dev/null || : + perf_pid= fi if test -n "$strans_pid"; then - kill "$strans_pid" 2>/dev/null || true - wait "$strans_pid" 2>/dev/null || true + kill "$strans_pid" 2>/dev/null || : + wait "$strans_pid" 2>/dev/null || : + strans_pid= fi + exit "$status" } -trap cleanup 0 1 2 15 +ibusready() +{ + for address in "$busdir"/*; do + test -f "$address" || continue + foundpid= + foundaddress= + while IFS= read -r line; do + case $line in + IBUS_DAEMON_PID="$strans_pid") foundpid=1 ;; + IBUS_ADDRESS=unix:abstract=strans-"$strans_pid",*) foundaddress=1 ;; + esac + done <"$address" + if test -n "$foundpid" && test -n "$foundaddress"; then + return 0 + fi + done + return 1 +} + +trap cleanup 0 +trap 'exit 129' 1 +trap 'exit 130' 2 +trap 'exit 143' 15 ./strans map "$@" & strans_pid=$! -sleep 1 -kill -0 "$strans_pid" + +attempt=0 +while test "$attempt" -lt 10; do + if test -S "$ipc" && ibusready; then + break + fi + if ! kill -0 "$strans_pid" 2>/dev/null; then + if wait "$strans_pid"; then + status=0 + else + status=$? + fi + strans_pid= + if test "$status" -eq 0; then + status=1 + fi + echo "bench.sh: daemon exited before publishing IPC and IBus endpoints" >&2 + exit "$status" + fi + attempt=$((attempt + 1)) + if test "$attempt" -lt 10; then + sleep 1 + fi +done +if test "$attempt" -eq 10; then + echo "bench.sh: daemon did not publish IPC and IBus endpoints within 10 seconds" >&2 + exit 1 +fi # warm up the renderer ./bench/bench bench/bench.keys 100 @@ -39,5 +106,5 @@ kill -0 "$perf_pid" ./bench/bench bench/bench.keys 100 kill -INT "$perf_pid" -wait "$perf_pid" 2>/dev/null || true +wait "$perf_pid" 2>/dev/null || : perf_pid= diff --git a/run.sh b/run.sh index 2e5bb45..8e371f0 100755 --- a/run.sh +++ b/run.sh @@ -1,6 +1,6 @@ #!/bin/sh -cd "$(dirname "$0")" +cd "$(dirname "$0")" || exit 1 if test "$#" -eq 0; then set -- @@ -20,8 +20,115 @@ if test "$#" -eq 0; then fi fi -pkill strans -sleep 1 +if ! test -x ./strans; then + echo "run.sh: ./strans is not executable; run make first" >&2 + exit 1 +fi +if test -n "${DISPLAY-}" && ! test -x xim/strans-xim; then + echo "run.sh: xim/strans-xim is not executable; run make first" >&2 + exit 1 +fi + +case ${XDG_RUNTIME_DIR-} in +/) ipc=/strans.sock ;; +/*/) ipc=${XDG_RUNTIME_DIR}strans.sock ;; +/*) ipc=${XDG_RUNTIME_DIR}/strans.sock ;; +*) ipc=/tmp/strans.$(id -u) ;; +esac +if test -n "${XDG_CONFIG_HOME-}"; then + busdir=$XDG_CONFIG_HOME/ibus/bus +elif test "${HOME+x}" = x; then + busdir=$HOME/.config/ibus/bus +else + echo "run.sh: HOME or XDG_CONFIG_HOME is required for IBus discovery" >&2 + exit 1 +fi + +strans_pid= +xim_pid= + +cleanup() +{ + status=$? + trap - 0 1 2 15 + if test -n "$xim_pid"; then + kill "$xim_pid" 2>/dev/null || : + wait "$xim_pid" 2>/dev/null || : + xim_pid= + fi + if test -n "$strans_pid"; then + kill "$strans_pid" 2>/dev/null || : + wait "$strans_pid" 2>/dev/null || : + strans_pid= + fi + exit "$status" +} + +ibusready() +{ + for address in "$busdir"/*; do + test -f "$address" || continue + foundpid= + foundaddress= + while IFS= read -r line; do + case $line in + IBUS_DAEMON_PID="$strans_pid") foundpid=1 ;; + IBUS_ADDRESS=unix:abstract=strans-"$strans_pid",*) foundaddress=1 ;; + esac + done <"$address" + if test -n "$foundpid" && test -n "$foundaddress"; then + return 0 + fi + done + return 1 +} + +trap cleanup 0 +trap 'exit 129' 1 +trap 'exit 130' 2 +trap 'exit 143' 15 + ./strans map "$@" & -sleep 1 +strans_pid=$! + +attempt=0 +while test "$attempt" -lt 10; do + if test -S "$ipc" && ibusready; then + break + fi + if ! kill -0 "$strans_pid" 2>/dev/null; then + wait "$strans_pid" + status=$? + strans_pid= + if test "$status" -eq 0; then + status=1 + fi + echo "run.sh: daemon exited before publishing IPC and IBus endpoints" >&2 + exit "$status" + fi + attempt=$((attempt + 1)) + if test "$attempt" -lt 10; then + sleep 1 + fi +done +if test "$attempt" -eq 10; then + echo "run.sh: daemon did not publish IPC and IBus endpoints within 10 seconds" >&2 + exit 1 +fi + +echo "run.sh: daemon $strans_pid is ready" +if test -z "${DISPLAY-}"; then + echo "run.sh: DISPLAY is unset; XIM will not be started" + wait "$strans_pid" + status=$? + strans_pid= + exit "$status" +fi + xim/strans-xim & +xim_pid=$! +echo "run.sh: started XIM $xim_pid; press Ctrl-C to stop both processes" +wait "$xim_pid" +status=$? +xim_pid= +exit "$status"