diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/hijack-prompt.bash | 167 | ||||
-rwxr-xr-x | src/twopane.bash | 32 | ||||
-rw-r--r-- | src/write-tty | 46 |
3 files changed, 186 insertions, 59 deletions
diff --git a/src/hijack-prompt.bash b/src/hijack-prompt.bash index f41dd17..6da5888 100755 --- a/src/hijack-prompt.bash +++ b/src/hijack-prompt.bash | |||
@@ -1,49 +1,38 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/bash |
2 | PS4=$'+ L\t$LINENO:\t' | ||
2 | case $- in | 3 | case $- in |
3 | *i* ) | 4 | *i* ) |
4 | set -m | 5 | ;; |
6 | *x* ) | ||
7 | exec bash --init-file "$0" -i -x -s "$@" | ||
5 | ;; | 8 | ;; |
6 | * ) | 9 | * ) |
7 | exec bash --init-file "$0" -i "$@" | 10 | exec bash --init-file "$0" -i -s "$@" |
8 | ;; | 11 | ;; |
9 | esac | 12 | esac |
10 | 13 | ||
11 | unhijack() | 14 | set -mx |
12 | { | ||
13 | case $# in | ||
14 | 0 ) | ||
15 | exec \ | ||
16 | 0<&$HIJACK_0 \ | ||
17 | 1>&$HIJACK_1 \ | ||
18 | 2>&$HIJACK_2 \ | ||
19 | {HIJACK_0}<&- \ | ||
20 | {HIJACK_1}>&- \ | ||
21 | {HIJACK_2}>&- | ||
22 | ;; | ||
23 | * ) | ||
24 | echo "history -d -1; unhijack; ${*@Q}" | ||
25 | ;; | ||
26 | esac | ||
27 | } | ||
28 | 15 | ||
29 | finally() | 16 | source ./src/finally.bash |
30 | { | ||
31 | exec \ | ||
32 | {HIJACK_0}<&0 \ | ||
33 | {HIJACK_1}>&1 \ | ||
34 | {HIJACK_2}>&2 \ | ||
35 | 0< <(unhijack eval "$1") \ | ||
36 | &> /dev/null | ||
37 | { | ||
38 | "${@:2}" | ||
39 | } <&$HIJACK_0 >&$HIJACK_1 2>&$HIJACK_2 | ||
40 | } | ||
41 | 17 | ||
42 | burld_read() | 18 | burld_read() |
43 | { | 19 | { |
44 | sleep 1 | 20 | while r=0; POSIXLY_CORRECT=y read -N1 -p '[hullo? burld?]> ' || r=$? |
45 | read -p '[hullo? burld?]> ' | 21 | do |
46 | echo "Burly ${REPLY:-Burld!}" | 22 | if (( r > 128 )) |
23 | then | ||
24 | sleep .25 | ||
25 | continue | ||
26 | elif [[ -n $REPLY ]] | ||
27 | then | ||
28 | echo "Burly ${REPLY:-Burld!}" | ||
29 | return 0 | ||
30 | else | ||
31 | echo "read returned $r" >&2 | ||
32 | return $r | ||
33 | fi | ||
34 | done | ||
35 | return 1 | ||
47 | } | 36 | } |
48 | 37 | ||
49 | quiet_fg() | 38 | quiet_fg() |
@@ -55,20 +44,124 @@ quiet_bg() | |||
55 | { | 44 | { |
56 | local STDERR | 45 | local STDERR |
57 | { | 46 | { |
58 | eval "$(printf '%q ' "$@") 2>&\$STDERR {STDERR}>&- &" | 47 | eval "$(printf '%q ' "$@") 2>&$STDERR $STDERR>&- &" |
59 | } {STDERR}>&2 2>/dev/null | 48 | } {STDERR}>&2 2>/dev/null |
60 | } | 49 | } |
61 | 50 | ||
62 | ring0() | 51 | ring0() |
63 | { | 52 | { |
64 | PS1="Burly boo\\\$ " | 53 | PS1="Burly ${SIGNAL:=bee}\\\$ " |
54 | } | ||
55 | |||
56 | lifetime() | ||
57 | { | ||
58 | [[ $$ != $BASHPID ]] && trap 'exit 0' INT | ||
59 | sleep "$1" & | ||
60 | if wait -f $! | ||
61 | then | ||
62 | kill "${@:2}" 2>/dev/null | ||
63 | true | ||
64 | else | ||
65 | return $? | ||
66 | fi | ||
67 | } | ||
68 | |||
69 | h() | ||
70 | { | ||
71 | quiet_bg sleep 5 | ||
72 | jobs -x quiet_bg lifetime 3 -INT %% | ||
73 | finally 'ring0' \ | ||
74 | quiet_fg %sleep | ||
75 | } | ||
76 | |||
77 | # Does this work? | ||
78 | g() | ||
79 | { | ||
80 | # lifetime 1 -INT $$ & | ||
81 | { burld_read; kill -INT $$; : reached ; } & | ||
82 | lifetime 3 -STOP $! & | ||
83 | PROMPT_COMMAND='pcmd fg' | ||
84 | fg | ||
85 | } | ||
86 | |||
87 | # Does this work? | ||
88 | g() | ||
89 | { | ||
90 | # lifetime 1 $$ & | ||
91 | { burld_read; kill -INT $$; : reached ; } & | ||
92 | lifetime 3 -INT $$ & disown | ||
93 | finally 'fg' eval 'sleep 3m & wait -f $!' | ||
94 | } | ||
95 | |||
96 | gn() | ||
97 | { | ||
98 | { burld_read; kill -INT $$; : reached ; } & | ||
99 | lifetime 3 -TSTP $! & disown | ||
100 | finally 'fg' fg | ||
101 | } | ||
102 | |||
103 | gp() | ||
104 | { | ||
105 | { burld_read; kill -INT $$; : reached ; } & | ||
106 | trap "finally fg :" SIGINT | ||
107 | lifetime 3 -INT $$ & disown | ||
108 | # finally 'fg' fg | ||
65 | } | 109 | } |
66 | 110 | ||
111 | # Interrupting read that works | ||
67 | f() | 112 | f() |
68 | { | 113 | { |
69 | quiet_bg burld_read | 114 | quiet_bg burld_read |
115 | jobs -x quiet_bg lifetime 3 -INT %% | ||
70 | finally 'ring0' \ | 116 | finally 'ring0' \ |
71 | quiet_fg burld_read | 117 | quiet_fg %burld_read |
118 | } | ||
119 | |||
120 | pcmd() | ||
121 | { | ||
122 | if [ "$PROMPT_COMMAND" ] | ||
123 | then | ||
124 | PROMPT_COMMAND= | ||
125 | "$@" | ||
126 | else | ||
127 | PROMPT_COMMAND="pcmd ${*@Q}" | ||
128 | fi | ||
129 | } | ||
130 | |||
131 | ff() | ||
132 | { | ||
133 | quiet_bg burld_read | ||
134 | jobs -x quiet_bg lifetime 3 -INT %% | ||
135 | pcmd ring0 | ||
136 | quiet_fg %burld_read | ||
137 | } | ||
138 | |||
139 | ring0gg() | ||
140 | { | ||
141 | kill -INT "$1" 2>/dev/null | ||
142 | PS1="Burly ${SIGNAL:=bee}\\\$ " | ||
72 | } | 143 | } |
73 | 144 | ||
145 | gg() | ||
146 | { | ||
147 | quiet_bg burld_read | ||
148 | jobs -x quiet_bg lifetime 3 -INT %% | ||
149 | finally "ring0gg $!" \ | ||
150 | quiet_fg %burld_read | ||
151 | } | ||
152 | |||
153 | DEBUG=y | ||
154 | |||
155 | trap 'SIGNAL=INT; : SIGINT' INT | ||
156 | |||
74 | PS1="[type 'f']\\\$ " | 157 | PS1="[type 'f']\\\$ " |
158 | |||
159 | case "$1" in | ||
160 | '' ) ;; | ||
161 | ff ) | ||
162 | "$1" | ||
163 | ;; | ||
164 | * ) | ||
165 | "$1" | ||
166 | ;; | ||
167 | esac | ||
diff --git a/src/twopane.bash b/src/twopane.bash index 59077fe..327d246 100755 --- a/src/twopane.bash +++ b/src/twopane.bash | |||
@@ -22,8 +22,8 @@ then | |||
22 | TOP_CMD="$SHELL -i" | 22 | TOP_CMD="$SHELL -i" |
23 | BOT_CMD=start | 23 | BOT_CMD=start |
24 | #TOP_EXIT=quit | 24 | #TOP_EXIT=quit |
25 | TOP_EXIT=prompt | 25 | #TOP_EXIT=prompt |
26 | #TOP_EXIT=restart | 26 | TOP_EXIT=restart |
27 | elif [ "$TWOPANE" -a "$*" = detach ] | 27 | elif [ "$TWOPANE" -a "$*" = detach ] |
28 | then | 28 | then |
29 | kill_tty_forward -TSTP | 29 | kill_tty_forward -TSTP |
@@ -245,18 +245,19 @@ start() | |||
245 | tty_forward() | 245 | tty_forward() |
246 | { | 246 | { |
247 | printf '%d\n' "$BASHPID" > "$TWOPANE"/tty_forward.pid | 247 | printf '%d\n' "$BASHPID" > "$TWOPANE"/tty_forward.pid |
248 | trap 'kill -INT $$' INT | ||
248 | read-tty | 249 | read-tty |
249 | } | 250 | } |
250 | 251 | ||
251 | TOP_PANE() | 252 | TOP_PANE() |
252 | { | 253 | { |
253 | (exec -a bottom-pane-tty-forward socat - UNIX-CONNECT:"$TWOPANE"/socket,forever) | 254 | (exec -a bottom-pane-tty-forward socat - UNIX-CONNECT:"$TWOPANE"/socket,forever) |
254 | x kill_tty_forward | 255 | x kill_tty_forward -STOP |
255 | case "$TOP_EXIT" in | 256 | case "$TOP_EXIT" in |
256 | restart ) | 257 | restart ) |
257 | # x kill -USR1 $$ | 258 | # x kill -USR1 $$ |
258 | x kill -INT $$ | 259 | x kill -INT $$ |
259 | with_screen_pane 1 start_screen_pane "$@" | 260 | # with_screen_pane 1 start_screen_pane "$@" |
260 | ;; | 261 | ;; |
261 | quit ) | 262 | quit ) |
262 | kill -INT $$ | 263 | kill -INT $$ |
@@ -313,7 +314,7 @@ background() | |||
313 | disconnect_sink ECHOSEND | 314 | disconnect_sink ECHOSEND |
314 | connect | 315 | connect |
315 | connect_sink ECHOSEND echo_sender | 316 | connect_sink ECHOSEND echo_sender |
316 | kill %tty_forward | 317 | kill %tty_forward 2>/dev/null |
317 | %tty_forward & | 318 | %tty_forward & |
318 | disown %tty_forward | 319 | disown %tty_forward |
319 | i 'starting tty_forward' | 320 | i 'starting tty_forward' |
@@ -379,6 +380,26 @@ SIGCHLD() | |||
379 | i "SIGCHILD: ${BASH_COMMAND@A}" | 380 | i "SIGCHILD: ${BASH_COMMAND@A}" |
380 | } | 381 | } |
381 | 382 | ||
383 | prompt_command() | ||
384 | { | ||
385 | set -- 'unset PROMPT_COMMAND; restart' | ||
386 | |||
387 | exec {FINALLY_0}<&0 {FINALLY_1}>&1 {FINALLY_2}>&2 | ||
388 | if ! [ "$DEBUG" ] | ||
389 | then | ||
390 | exec &>/dev/null | ||
391 | fi | ||
392 | cmd="history -d -1; exec <&$FINALLY_0 >&$FINALLY_1 >&$FINALLY_2; $*" | ||
393 | exec <<< "$cmd" | ||
394 | } | ||
395 | |||
396 | SIGINT() | ||
397 | { | ||
398 | i INT "${BASH_COMMAND@A}" | ||
399 | kill $TOP_PANE_PID $ECHOSEND_PID 2>/dev/null | ||
400 | PROMPT_COMMAND=prompt_command | ||
401 | } | ||
402 | |||
382 | our_bashrc_main() | 403 | our_bashrc_main() |
383 | { | 404 | { |
384 | BASH_ARGV0=twopane | 405 | BASH_ARGV0=twopane |
@@ -388,6 +409,7 @@ our_bashrc_main() | |||
388 | set -o pipefail | 409 | set -o pipefail |
389 | trap 'SIGUSR1' USR1 | 410 | trap 'SIGUSR1' USR1 |
390 | # trap 'SIGCHLD' CHLD | 411 | # trap 'SIGCHLD' CHLD |
412 | trap 'SIGINT' INT | ||
391 | trap '! [ "$DEBUG" ] || read -p "Exit> "; quit' EXIT | 413 | trap '! [ "$DEBUG" ] || read -p "Exit> "; quit' EXIT |
392 | export PS1="$BOT_TITLE\\\$ " | 414 | export PS1="$BOT_TITLE\\\$ " |
393 | } | 415 | } |
diff --git a/src/write-tty b/src/write-tty index fbe62ea..8fdb78f 100644 --- a/src/write-tty +++ b/src/write-tty | |||
@@ -10,7 +10,7 @@ output_filter() | |||
10 | chr() | 10 | chr() |
11 | { | 11 | { |
12 | declare -i n="$*" | 12 | declare -i n="$*" |
13 | printf "\\$(printf %o "$n")" | 13 | printf "$(printf '\%o' "$n")" |
14 | } | 14 | } |
15 | 15 | ||
16 | colorize() | 16 | colorize() |
@@ -20,25 +20,29 @@ colorize() | |||
20 | while read -r | 20 | while read -r |
21 | do | 21 | do |
22 | case "$REPLY" in | 22 | case "$REPLY" in |
23 | \\[0-7][0-7][0-7] ) ;; | 23 | \\[0-7][0-7][0-7] ) |
24 | declare -i c=8#"${REPLY#?}" | ||
25 | ;; | ||
26 | \\U[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] ) | ||
27 | declare -i c=16#"${REPLY#??}" | ||
28 | ;; | ||
24 | * ) | 29 | * ) |
25 | printf '%s\n' "$REPLY" | 30 | printf '%s\n' "$REPLY" |
26 | continue | 31 | continue |
27 | ;; | 32 | ;; |
28 | esac | 33 | esac |
29 | declare -i c=8#"${REPLY#?}" | ||
30 | if (( c > 128 + 127 )) | 34 | if (( c > 128 + 127 )) |
31 | then | 35 | then |
32 | : | 36 | : |
33 | elif (( c > 128 + 32 )) | 37 | elif (( c > 128 + 32 )) |
34 | then | 38 | then |
35 | printf -v REPLY "M-$(chr c - 128)" | 39 | REPLY=M-$(chr c - 128) |
36 | elif (( c > 127 )) | 40 | elif (( c > 127 )) |
37 | then | 41 | then |
38 | printf -v REPLY "M-^$(chr c - 128 + 64)" | 42 | REPLY=M-^$(chr c - 128 + 64) |
39 | elif (( c < 32 )) | 43 | elif (( c < 32 )) |
40 | then | 44 | then |
41 | printf -v REPLY "^$(chr c + 64)" | 45 | REPLY=^$(chr c + 64) |
42 | fi | 46 | fi |
43 | printf $'\e[106m%s\e[m\n' "$REPLY" | 47 | printf $'\e[106m%s\e[m\n' "$REPLY" |
44 | done | 48 | done |
@@ -48,7 +52,7 @@ tokenize() | |||
48 | { | 52 | { |
49 | BASH_ARGV0=tokenize | 53 | BASH_ARGV0=tokenize |
50 | echo -n "$0" >/proc/$BASHPID/comm | 54 | echo -n "$0" >/proc/$BASHPID/comm |
51 | while read -r -N1 | 55 | while read -r -n1 -d '' |
52 | do | 56 | do |
53 | if [[ "$REPLY" =~ [[:print:]] ]] | 57 | if [[ "$REPLY" =~ [[:print:]] ]] |
54 | then | 58 | then |
@@ -56,13 +60,26 @@ tokenize() | |||
56 | # multibyte unicode character. | 60 | # multibyte unicode character. |
57 | printf '%s\n' "$REPLY" | 61 | printf '%s\n' "$REPLY" |
58 | continue | 62 | continue |
59 | else | 63 | elif [ "$REPLY" ] |
64 | then | ||
60 | # If it is a non-printable, then we output a | 65 | # If it is a non-printable, then we output a |
61 | # multi-character line. In this case we colorize it | 66 | # multi-character line. In this case we colorize it |
62 | # later so that it won't be confused with multiple | 67 | # later so that it won't be confused with multiple |
63 | # printable characters in the . | 68 | # printable characters. |
64 | printf '\\%.3o\n' "'$REPLY" | 69 | bytelen=$(LC_ALL=C; echo ${#REPLY}) |
65 | continue | 70 | if (( bytelen == 1 )) |
71 | then | ||
72 | printf '\\%.3o\n' "'$REPLY" | ||
73 | else | ||
74 | hexdigits=$(LC_ALL=C; for ((i=0; i<$bytelen; ++i)) | ||
75 | do | ||
76 | printf '%.2x' "'${REPLY:$i:1}" | ||
77 | printf '%.2x\n' "'${REPLY:$i:1}" >&2 | ||
78 | done) | ||
79 | printf '%s%.8x\n' '\U' 0x"$hexdigits" | ||
80 | fi | ||
81 | else | ||
82 | printf '\\%.3o\n' 0 | ||
66 | fi | 83 | fi |
67 | done | 84 | done |
68 | } | 85 | } |
@@ -81,9 +98,4 @@ soft_cursor() | |||
81 | done | 98 | done |
82 | } | 99 | } |
83 | 100 | ||
84 | if [ -t 1 ] | 101 | output_filter |
85 | then | ||
86 | output_filter | ||
87 | else | ||
88 | exec -a write-tty-raw socat - - | ||
89 | fi | ||