(bash) シェル スクリプトをネイティブ メッセージング ホストとして使用しないことをお勧めします。
read
パラメーターを指定しないと、終了する前に行全体が読み取られますが、ネイティブ メッセージング プロトコルでは、最初の 4 バイトが次のメッセージの長さ (ネイティブ バイト順) を指定することが指定されています。
Bash は、バイナリ データを処理するためのひどいツールです。read
コマンドの改良版では、パラメータを指定して、文字 (注: バイトではない) の-n N
後の読み取りを停止し、一部の処理を削除します。たとえば、次のようにすると、最初の 4 文字が という変数に格納されます。N
-r
var_prefix
IFS= read -rn 4 var_prefix
これで最初の 4 バイトが変数に格納されると仮定しても (そうではありません!)、バイトを整数に変換する必要があります。bash がすべての NUL バイトを自動的に削除することは既に述べましたか? この特性により、完全に機能するネイティブ メッセージング ホストとしての Bash はまったく価値がありません。
{
最初の数バイトを無視することでこの欠点に対処し、JSON 形式の要求の先頭にある文字を見つけたら結果の解析を開始できます。この後、入力の最後が見つかるまですべての入力を読み取る必要があります。JSON 文字列の末尾に到達したときに入力の読み取りを停止する JSON パーサーが必要です。それを書いて頑張ってください。
出力の生成は簡単です。echo -n
またはを使用するだけprintf
です。
}
これは、入力が で終了し、それを (処理なしで) 読み取り、結果を返すことを前提とした最小限の例です。このデモは機能しますが、bash を使用するのではなく、Python や C++ などのよりリッチな (スクリプト) 言語を使用することを強くお勧めします。
#!/bin/bash
# Loop forever, to deal with chrome.runtime.connectNative
while IFS= read -r -n1 c; do
# Read the first message
# Assuming that the message ALWAYS ends with a },
# with no }s in the string. Adopt this piece of code if needed.
if [ "$c" != '}' ] ; then
continue
fi
message='{"message": "Hello world!"}'
# Calculate the byte size of the string.
# NOTE: This assumes that byte length is identical to the string length!
# Do not use multibyte (unicode) characters, escape them instead, e.g.
# message='"Some unicode character:\u1234"'
messagelen=${#message}
# Convert to an integer in native byte order.
# If you see an error message in Chrome's stdout with
# "Native Messaging host tried sending a message that is ... bytes long.",
# then just swap the order, i.e. messagelen1 <-> messagelen4 and
# messagelen2 <-> messagelen3
messagelen1=$(( ($messagelen ) & 0xFF ))
messagelen2=$(( ($messagelen >> 8) & 0xFF ))
messagelen3=$(( ($messagelen >> 16) & 0xFF ))
messagelen4=$(( ($messagelen >> 24) & 0xFF ))
# Print the message byte length followed by the actual message.
printf "$(printf '\\x%x\\x%x\\x%x\\x%x' \
$messagelen1 $messagelen2 $messagelen3 $messagelen4)%s" "$message"
done