
そこで、キーボードLED(numlockとcapslock)を使用してデータを転送できるシンプルなBashスクリプトを作成しました(LTTの「Do Not Plug This USB In! – Hak5 Rubber Ducky」ビデオからインスピレーションを得ました)。これは私のスクリプトです。
#!/bin/bash
for i in `cat /dev/stdin | perl -lpe '$_=unpack"B*"' | sed 's/./\ &/g'`
do export E=`expr $E + 1`
echo "Bit number $E has a value of $i"
if (( $i == 0 ))
then
xdotool key Caps_Lock
sleep 0.1
xdotool key Caps_Lock
else
xdotool key Num_Lock
sleep 0.1
xdotool key Num_Lock
fi
done
他の点は、キーボードのLEDが共通の高さではなく共通の低さであることです(これは、Linusのビデオと比較してLEDが長時間消えていることを意味します)。しかし、欠陥があります。 stdinでEOFが出るのを待ちますが、これは私が望むものではありません。私はそれがstdinに書き込まれたときにデータを読み取るミニモデムのように動作したいです(まあ、少なくとも改行文字の後)。次のことなくこれを行う方法はありますか?
- プログラミング言語を変更して
- スクリプト全体を壊さないで?
よろしくお願いします。
答え1
これを行う方法はいくつかあります。すでにPerlでタスクの一部を実行しているので、最も簡単な方法は、おそらく次のようにPerlですべてのタスクを実行することです。用語::読み取りキー基準寸法。たとえば、
#!/usr/bin/perl -l
use Term::ReadKey;
# trap INT so we can reset the terminal on ^C
$SIG{INT} = sub { exit };
ReadMode 3;
while ($_ = ReadKey 0) {
last if m/\cD/;
@bits = split //, unpack "B*";
for my $i (0..$#bits) {
print "Bit number $i has a value of $bits[$i]";
if ($bits[$i] == 0) {
system("xdotool key Caps_Lock; sleep 0.1; xdotool key Caps_Lock");
} else {
system("xdotool key Num_Lock; sleep 0.1; xdotool key Num_Lock");
};
};
};
END {
ReadMode 0;
};
または、CPANからモジュールをインストールしたくない場合は、で説明されてstty
いるperldoc -f getc
方法を使用してgetc
一度に1文字ずつ読み取ることができます。またはsetattr()
。stty
ただし、bash(およびcat&perl&sed)でこれを行うには、次のことに基づいて何かを試してみてください。
cat
まず、stdinですでに読み取ることができるプログラム(Perlやsedや他のほとんどすべての操作が実行できる)にデータをパイプする必要がないことを認識してください。その後、Perlの出力をsedにパイプするたびに、おそらく何か間違ったことをしている可能性が高く、sedで行ったすべてのことをPerlスクリプトで実行できることに気づきました。 Perl には sed と同様に as/// 演算子もあります。
mapfile
bashに配列があることを覚えておいてください。 bash 組み込み関数を使用して、プログラムの出力を配列として読み取ることができます。プロセスの交換。
そして
- bashは一度に1文字ずつ読み取るために使用できます
read -n 1
。
#!/bin/bash
while read -n 1 char ; do
case "$char" in
$'\004') break ;; # Ctrl-D
esac
# This uses perl to print each bit separated by a newline. we could do it with s/// in perl,
# but here i'm using split and join. the output from perl is read into bash array $bits.
mapfile -t bits < <(printf '%s' "$char" | perl -lne 'print join("\n", split //, unpack"B*")')
# that expr stuff is incredibly ugly. and decades obsolete for shell arithmetic.
# i'm going to use let instead because I also find (( i=i+1 )) to be incredibly ugly.
count=0
for i in "${bits[@]}" ; do
let count+=1
echo "Bit number $count has a value of $i"
if [ "$i" -eq 0 ] ; then
xdotool key Caps_Lock
sleep 0.1
xdotool key Caps_Lock
else
xdotool key Num_Lock
sleep 0.1
xdotool key Num_Lock
fi
done
done