Compare commits
2 Commits
24e380651c
...
279b9230a4
| Author | SHA1 | Date | |
|---|---|---|---|
| 279b9230a4 | |||
| c2cb18cbdd |
241
README.md
241
README.md
@@ -1,63 +1,34 @@
|
||||
# strans
|
||||
|
||||
strans is a small, single-user input method for Korean, Japanese, English,
|
||||
and emoji. It provides one engine shared by IBus, XIM, and GTK 3 frontends.
|
||||
The existing Vietnamese Telex mode remains available for compatibility, but
|
||||
is not an actively developed language mode.
|
||||
emoji, and symbols. It provides one engine for IBus, XIM, and GTK 3.
|
||||
Vietnamese Telex is also available as a compatibility mode.
|
||||
|
||||
## Input behavior
|
||||
## Input modes
|
||||
|
||||
English is direct passthrough. Korean uses 2-beolsik composition. Japanese
|
||||
Hiragana keeps the complete kana reading until it is committed, so `kanji`
|
||||
forms `かんじ` and offers whole-reading candidates such as `漢字` and `幹事`.
|
||||
An apostrophe resolves an ambiguous `n` without forwarding the apostrophe:
|
||||
for example, `n'ya` forms `んや`. Katakana is direct Katakana composition
|
||||
and does not perform Kanji dictionary conversion.
|
||||
| Key | Mode |
|
||||
| --- | --- |
|
||||
| `Ctrl+N` | Japanese Hiragana and Kanji conversion |
|
||||
| `Ctrl+K` | Japanese Katakana |
|
||||
| `Ctrl+S` | Korean Hangul (2-beolsik) |
|
||||
| `Ctrl+T` | English |
|
||||
| `Ctrl+V` | Vietnamese Telex |
|
||||
| `Ctrl+E` | Emoji and symbol search |
|
||||
| `Ctrl+H` | One-shot Hanja search |
|
||||
| `Ctrl+P` | Toggle popup preedit |
|
||||
|
||||
A Japanese composition is committed by Enter, candidate selection, a real
|
||||
input boundary, or an explicit mode change. Backspace first removes pending
|
||||
romaji, then accumulated kana. The Japanese modes support doubled consonants
|
||||
and combinations such as `nya`, `nnya`, and `matcha`.
|
||||
Use `Up`/`Down` to move through candidates, `Enter` or `1`-`9` to select,
|
||||
`Tab` to cycle temporary search results, and `Esc` to cancel. `0` commits the
|
||||
current reading without conversion.
|
||||
|
||||
Modes and temporary searches use Ctrl and one letter:
|
||||
|
||||
```text
|
||||
Ctrl+N Japanese Hiragana and Kanji conversion
|
||||
Ctrl+K Japanese Katakana
|
||||
Ctrl+S Korean Hangul
|
||||
Ctrl+T English passthrough
|
||||
Ctrl+V Vietnamese Telex compatibility mode
|
||||
Ctrl+E Emoji and symbol search
|
||||
Ctrl+H One-shot Hanja search
|
||||
Ctrl+P Toggle popup preedit
|
||||
```
|
||||
|
||||
While candidates are visible, Up and Down move the selection, Enter accepts
|
||||
the selected candidate, and an unmodified `1`-`9` selects the corresponding
|
||||
visible row. Tab cycles temporary search results. `0` commits an unconverted
|
||||
language reading. Escape cancels the current composition. Ctrl, Alt, or
|
||||
Super combined with a number does not select a candidate.
|
||||
|
||||
Emoji search is temporary and returns to the previous mode. Queries may use
|
||||
English aliases or the active language's input rules, including Japanese
|
||||
`egao` becoming `えがお` or `エガオ`:
|
||||
|
||||
```text
|
||||
Ctrl+E → smile → Enter → 😀
|
||||
```
|
||||
|
||||
Hanja search is temporary and returns to the active language after one
|
||||
conversion. Press Ctrl+H and type with that language's normal input rules,
|
||||
then select with Up, Down, Tab, Enter, or `1`-`9`. The bundled dictionary
|
||||
currently indexes exactly one modern Hangul syllable. Incomplete jamo,
|
||||
multiple syllables, and other languages therefore have no candidates; Enter
|
||||
commits the displayed reading unchanged. Escape cancels the search. It does
|
||||
not convert words or text already surrounding the cursor.
|
||||
Hiragana mode composes a complete reading before offering Kanji candidates.
|
||||
Katakana mode does not perform Kanji conversion. Emoji and Hanja searches
|
||||
return to the previous mode after use. Hanja lookup currently supports one
|
||||
modern Hangul syllable at a time.
|
||||
|
||||
## Build and test
|
||||
|
||||
The supported build uses Docker so host and container toolchains are not
|
||||
mixed. Only Docker and Make are needed on the host:
|
||||
Docker is the supported build environment:
|
||||
|
||||
```sh
|
||||
git submodule update --init
|
||||
@@ -66,12 +37,7 @@ make docker-build
|
||||
make docker-check
|
||||
```
|
||||
|
||||
`docker-image` creates the Arch Linux dependency image, `docker-build`
|
||||
compiles the runtime components, and `docker-check` runs the map verifiers and
|
||||
test suites. Docker targets force their own compilation, so newer host
|
||||
objects cannot be reused. `docker` is a convenience alias for the image and
|
||||
build steps.
|
||||
The resulting runtime artifacts are:
|
||||
Build output:
|
||||
|
||||
```text
|
||||
strans daemon and IBus frontend
|
||||
@@ -79,12 +45,44 @@ xim/strans-xim XIM frontend
|
||||
gtk/im-strans.so GTK 3 frontend
|
||||
```
|
||||
|
||||
Use `make docker-check TESTARGS=hangul` to filter the C unit tests. A native
|
||||
build is still possible with the dependencies and Plan 9 setup recorded in
|
||||
`Dockerfile`; use `make all`, `make check`, and `make bench` inside that
|
||||
environment.
|
||||
Use `make docker-check TESTARGS=hangul` to run selected C tests. Native
|
||||
`make all`, `make check`, and `make bench` are also available when the
|
||||
dependencies listed in [`Dockerfile`](Dockerfile) are installed.
|
||||
|
||||
After editing an input source, regenerate and verify its dictionary with:
|
||||
## Run
|
||||
|
||||
The popup needs one to four scalable font files. No fonts are bundled.
|
||||
`run.sh` uses installed DejaVu, Jigmo, or Noto CJK fonts when available, or
|
||||
accepts explicit files in fallback order:
|
||||
|
||||
```sh
|
||||
./run.sh
|
||||
./run.sh /path/to/primary.ttf /path/to/fallback.ttc
|
||||
```
|
||||
|
||||
The script starts the daemon and, when `DISPLAY` is set, the XIM frontend. It
|
||||
restarts any existing `strans` processes owned by the current user.
|
||||
|
||||
Configure clients as needed:
|
||||
|
||||
```sh
|
||||
# XIM
|
||||
export XMODIFIERS=@im=strans
|
||||
|
||||
# GTK 3 module
|
||||
doas make -C gtk install
|
||||
|
||||
# IBus client example
|
||||
GLFW_IM_MODULE=ibus kitty
|
||||
```
|
||||
|
||||
strans provides its own IBus endpoint; `ibus-daemon` and fcitx are not
|
||||
required. Without `DISPLAY`, the daemon and IBus frontend still work, but the
|
||||
popup is disabled.
|
||||
|
||||
## Dictionary data
|
||||
|
||||
After changing an input source, regenerate and verify the dictionaries:
|
||||
|
||||
```sh
|
||||
map/mkemoji >map/emoji.dict
|
||||
@@ -92,119 +90,12 @@ map/mkhanja >map/hanja.dict
|
||||
make verify-map
|
||||
```
|
||||
|
||||
Hanja import and Japanese dictionary regeneration are documented in
|
||||
[`map/README`](map/README). The converter output is deterministic UTF-8,
|
||||
tab-separated data consumable by the runtime dictionary reader.
|
||||
See [`map/README`](map/README) for Hanja import and Japanese dictionary
|
||||
generation.
|
||||
|
||||
## Run and install
|
||||
## Licensing
|
||||
|
||||
Install one or more scalable outline fonts, then pass their files in fallback
|
||||
order after the map directory. The daemon accepts at most four font files and
|
||||
does not search the system font database. For example, the Docker-tested Arch
|
||||
packages and paths are:
|
||||
|
||||
```sh
|
||||
doas pacman -S ttf-dejavu ttf-jigmo
|
||||
./strans map \
|
||||
/usr/share/fonts/TTF/DejaVuSans.ttf \
|
||||
/usr/share/fonts/TTF/Jigmo.ttf \
|
||||
/usr/share/fonts/TTF/Jigmo2.ttf &
|
||||
```
|
||||
|
||||
These fonts are test fixtures, not runtime requirements. Any suitable
|
||||
scalable outline files may be supplied; their argument order is the glyph
|
||||
fallback order. A collection file uses its first face. If any named file is
|
||||
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:
|
||||
|
||||
```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. On repeated
|
||||
invocation, it stops a previous live `run.sh` only after confirming that the
|
||||
old launcher directly owns the daemon serving the same IPC and IBus
|
||||
endpoints and that the daemon carries that launcher's PID and process-start
|
||||
identity. A manually started or orphaned daemon is left untouched and
|
||||
reported as 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
|
||||
fallback `/tmp/strans.<uid>`. A second daemon will not replace a live
|
||||
daemon's socket.
|
||||
|
||||
For XIM applications:
|
||||
|
||||
```sh
|
||||
./xim/strans-xim &
|
||||
export XMODIFIERS=@im=strans
|
||||
xterm
|
||||
```
|
||||
|
||||
For GTK 3 applications, install the module built by Docker. Installation
|
||||
needs the GTK 3 runtime, but not its development package:
|
||||
|
||||
```sh
|
||||
doas make -C gtk install
|
||||
```
|
||||
|
||||
`LIBDIR` defaults to `/usr/lib` and may be overridden for another system.
|
||||
Normal `DESTDIR` semantics are supported, and a staged install does not update
|
||||
the host GTK module cache:
|
||||
|
||||
```sh
|
||||
make -C gtk install DESTDIR="$pkgdir"
|
||||
```
|
||||
|
||||
For IBus clients such as kitty:
|
||||
|
||||
```sh
|
||||
GLFW_IM_MODULE=ibus kitty
|
||||
```
|
||||
|
||||
strans provides its own IBus endpoint; neither ibus-daemon nor fcitx is
|
||||
required. Starting without `DISPLAY` is supported: input processing and IBus
|
||||
continue to run while the optional X popup is disabled.
|
||||
|
||||
## Ownership and rendering constraints
|
||||
|
||||
There is one global composition, not one independent engine per frontend
|
||||
context. The first meaningful key from a new context resets the previous
|
||||
composition and transfers ownership. Reset, focus loss, context destruction,
|
||||
and disconnect affect the engine only when they come from its active owner;
|
||||
stale events cannot clear a newer owner's preedit.
|
||||
|
||||
The popup is an optional X window. It uses the explicit font-file order and
|
||||
fixed-width rune cells; U+FE0E and U+FE0F variation selectors use zero cells.
|
||||
It does not perform OpenType shaping, color-emoji rendering, or general
|
||||
grapheme clustering. Multi-rune emoji are committed intact but are drawn as
|
||||
their constituent rune cells under this boundary. A supplied caret rectangle
|
||||
is used when available, with the pointer as fallback. The X renderer accepts
|
||||
only a 24-depth, 32-bpp TrueColor root format and disables itself cleanly on
|
||||
other visuals.
|
||||
|
||||
## Data, third-party code, and licensing
|
||||
|
||||
Data and third-party provenance is recorded in
|
||||
[`docs/PROVENANCE.md`](docs/PROVENANCE.md), with font-specific details in
|
||||
[`font/PROVENANCE`](font/PROVENANCE). No font binaries are bundled; that file
|
||||
retains the provenance of the faces formerly kept in the repository. The
|
||||
historical SKK-derived Kanji
|
||||
dictionary is distributed under GPL version 2 or later; its license text is
|
||||
in [`LICENSES/GPL-2.0-or-later.txt`](LICENSES/GPL-2.0-or-later.txt).
|
||||
The single-character Hanja data derived from libhangul is distributed under
|
||||
the BSD 3-Clause license in
|
||||
[`LICENSES/BSD-3-Clause-libhangul-hanja.txt`](LICENSES/BSD-3-Clause-libhangul-hanja.txt).
|
||||
|
||||
The repository does not currently declare a license for the strans project
|
||||
source as a whole. The licenses of bundled data, historical font assets, and
|
||||
third-party components do not by themselves license the original strans
|
||||
source.
|
||||
Data and third-party notices are in
|
||||
[`docs/PROVENANCE.md`](docs/PROVENANCE.md) and
|
||||
[`font/PROVENANCE`](font/PROVENANCE). The repository does not currently
|
||||
declare a license for the strans source as a whole.
|
||||
|
||||
309
run.sh
309
run.sh
@@ -1,8 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
root=$(pwd -P) || exit 1
|
||||
uid=$(id -u) || exit 1
|
||||
|
||||
if test "$#" -eq 0; then
|
||||
set --
|
||||
@@ -12,9 +10,7 @@ if test "$#" -eq 0; then
|
||||
/usr/share/fonts/TTF/Jigmo2.ttf \
|
||||
/usr/share/fonts/noto/NotoSansCJK-Regular.ttc
|
||||
do
|
||||
if test -f "$font"; then
|
||||
set -- "$@" "$font"
|
||||
fi
|
||||
test -f "$font" && set -- "$@" "$font"
|
||||
done
|
||||
if test "$#" -eq 0; then
|
||||
echo "run.sh: no default font found; pass a font file" >&2
|
||||
@@ -30,297 +26,24 @@ 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
|
||||
if ! command -v pkill >/dev/null 2>&1; then
|
||||
echo "run.sh: pkill is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
strans_pid=
|
||||
xim_pid=
|
||||
old_daemon_pid=
|
||||
old_daemon_start=
|
||||
old_launcher_pid=
|
||||
old_launcher_start=
|
||||
uid=$(id -u) || exit 1
|
||||
pkill -TERM -u "$uid" -x strans-xim 2>/dev/null || :
|
||||
pkill -TERM -u "$uid" -x strans 2>/dev/null || :
|
||||
sleep 0.1
|
||||
pkill -KILL -u "$uid" -x strans-xim 2>/dev/null || :
|
||||
pkill -KILL -u "$uid" -x strans 2>/dev/null || :
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
procuid()
|
||||
{
|
||||
{
|
||||
while IFS=' ' read -r key real effective saved filesystem rest; do
|
||||
case $key in
|
||||
Uid:)
|
||||
test "$real" = "$effective" &&
|
||||
test "$real" = "$saved" &&
|
||||
test "$real" = "$filesystem" || return 1
|
||||
printf '%s\n' "$real"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done <"/proc/$1/status"
|
||||
} 2>/dev/null
|
||||
return 1
|
||||
}
|
||||
|
||||
procparent()
|
||||
{
|
||||
{
|
||||
while IFS=' ' read -r key value rest; do
|
||||
case $key in
|
||||
PPid:) printf '%s\n' "$value"; return 0 ;;
|
||||
esac
|
||||
done <"/proc/$1/status"
|
||||
} 2>/dev/null
|
||||
return 1
|
||||
}
|
||||
|
||||
procstart()
|
||||
{
|
||||
proc_stat=
|
||||
{ IFS= read -r proc_stat <"/proc/$1/stat"; } 2>/dev/null || return 1
|
||||
proc_stat=${proc_stat##*) }
|
||||
set -- $proc_stat
|
||||
test "$#" -ge 20 || return 1
|
||||
test "$1" != Z || return 1
|
||||
printf '%s\n' "${20}"
|
||||
}
|
||||
|
||||
sameproc()
|
||||
{
|
||||
test -n "$2" || return 1
|
||||
proc_now=$(procstart "$1") || return 1
|
||||
test "$proc_now" = "$2"
|
||||
}
|
||||
|
||||
listeninginode()
|
||||
{
|
||||
listener_inode=
|
||||
listener_count=0
|
||||
{
|
||||
while IFS=' ' read -r num ref proto flags type state inode path; do
|
||||
if test "$flags" = 00010000 && test "$type" = 0001 &&
|
||||
test "$state" = 01 && test "$path" = "$1"; then
|
||||
listener_inode=$inode
|
||||
listener_count=$((listener_count + 1))
|
||||
fi
|
||||
done </proc/net/unix
|
||||
} 2>/dev/null
|
||||
test "$listener_count" -eq 1 || return 1
|
||||
printf '%s\n' "$listener_inode"
|
||||
}
|
||||
|
||||
socketowned()
|
||||
{
|
||||
socket_inode=$(listeninginode "$2") || return 1
|
||||
for socket_fd in "/proc/$1/fd"/*; do
|
||||
test "$(readlink "$socket_fd" 2>/dev/null)" = \
|
||||
"socket:[$socket_inode]" && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
validdaemon()
|
||||
{
|
||||
test "$(procuid "$1")" = "$uid" || return 1
|
||||
test "$(readlink "/proc/$1/cwd" 2>/dev/null)" = "$root" || return 1
|
||||
daemon_exe=$(readlink "/proc/$1/exe" 2>/dev/null) || return 1
|
||||
case $daemon_exe in
|
||||
"$root/strans"|"$root/strans (deleted)") ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
test -S "$ipc" || return 1
|
||||
socketowned "$1" "$ipc" || return 1
|
||||
socketowned "$1" "@strans-$1"
|
||||
}
|
||||
|
||||
finddaemon()
|
||||
{
|
||||
old_daemon_pid=
|
||||
old_daemon_start=
|
||||
for address in "$busdir"/*; do
|
||||
test -f "$address" || continue
|
||||
address_pid=
|
||||
address_ok=
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
IBUS_DAEMON_PID=*) address_pid=${line#IBUS_DAEMON_PID=} ;;
|
||||
esac
|
||||
done <"$address"
|
||||
case $address_pid in
|
||||
''|*[!0-9]*) continue ;;
|
||||
esac
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
IBUS_ADDRESS=unix:abstract=strans-"$address_pid",*)
|
||||
address_ok=1 ;;
|
||||
esac
|
||||
done <"$address"
|
||||
test -n "$address_ok" || continue
|
||||
validdaemon "$address_pid" || continue
|
||||
address_start=$(procstart "$address_pid") || continue
|
||||
validdaemon "$address_pid" || continue
|
||||
old_daemon_pid=$address_pid
|
||||
old_daemon_start=$address_start
|
||||
return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
findlauncher()
|
||||
{
|
||||
launcher_env=$({ tr '\000' '\n' <"/proc/$old_daemon_pid/environ"; } \
|
||||
2>/dev/null) || return 1
|
||||
old_launcher_pid=$(printf '%s\n' "$launcher_env" |
|
||||
sed -n 's/^STRANS_RUN_OWNER_PID=//p')
|
||||
old_launcher_start=$(printf '%s\n' "$launcher_env" |
|
||||
sed -n 's/^STRANS_RUN_OWNER_START=//p')
|
||||
case $old_launcher_pid in
|
||||
''|*[!0-9]*|0|1|"$$") return 1 ;;
|
||||
esac
|
||||
case $old_launcher_start in
|
||||
''|*[!0-9]*) return 1 ;;
|
||||
esac
|
||||
test "$(procuid "$old_launcher_pid")" = "$uid" || return 1
|
||||
test "$(readlink "/proc/$old_launcher_pid/cwd" 2>/dev/null)" = "$root" ||
|
||||
return 1
|
||||
sameproc "$old_launcher_pid" "$old_launcher_start" || return 1
|
||||
sameproc "$old_daemon_pid" "$old_daemon_start" || return 1
|
||||
test "$(procparent "$old_daemon_pid")" = "$old_launcher_pid" || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
stoplauncher()
|
||||
{
|
||||
sameproc "$old_daemon_pid" "$old_daemon_start" || return 1
|
||||
test "$(procparent "$old_daemon_pid")" = "$old_launcher_pid" || return 1
|
||||
sameproc "$old_launcher_pid" "$old_launcher_start" || return 1
|
||||
kill "$old_launcher_pid" 2>/dev/null || return 1
|
||||
echo "run.sh: stopping previous launcher $old_launcher_pid (daemon $old_daemon_pid)"
|
||||
|
||||
stop_attempt=0
|
||||
while test "$stop_attempt" -lt 10; do
|
||||
if ! sameproc "$old_launcher_pid" "$old_launcher_start" &&
|
||||
! sameproc "$old_daemon_pid" "$old_daemon_start"; then
|
||||
return 0
|
||||
fi
|
||||
stop_attempt=$((stop_attempt + 1))
|
||||
if test "$stop_attempt" -lt 10; then
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
echo "run.sh: previous launcher did not stop within 10 seconds" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
trap cleanup 0
|
||||
trap 'exit 129' 1
|
||||
trap 'exit 130' 2
|
||||
trap 'exit 143' 15
|
||||
|
||||
launcher_start=$(procstart "$$") || {
|
||||
echo "run.sh: cannot read launcher process identity from /proc" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if finddaemon; then
|
||||
if ! findlauncher; then
|
||||
echo "run.sh: daemon $old_daemon_pid owns the current endpoints but has no" >&2
|
||||
echo "run.sh: live run.sh owner; leaving it untouched (stop it once, then retry)" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! stoplauncher; then
|
||||
echo "run.sh: previous launcher did not stop cleanly; refusing to start another daemon" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
STRANS_RUN_OWNER_PID=$$ STRANS_RUN_OWNER_START=$launcher_start \
|
||||
./strans map "$@" &
|
||||
./strans map "$@" </dev/null &
|
||||
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
|
||||
if test -n "${DISPLAY-}"; then
|
||||
xim/strans-xim </dev/null &
|
||||
xim_pid=$!
|
||||
echo "run.sh: started daemon $strans_pid and XIM $xim_pid"
|
||||
else
|
||||
echo "run.sh: started daemon $strans_pid; DISPLAY is unset"
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user