ターミナルを制御するばあいは、termio構造体を使う。
これは、ヘッダファイルの/usr/include/asm/termios.hを
見ると、次のようになっている。
#include <asm/termbits.h> #define NCC 8 struct termio { unsigned short c_iflag; /* input mode flags */ unsigned short c_oflag; /* output mode flags */ unsigned short c_cflag; /* control mode flags */ unsigned short c_lflag; <-- これ /* local mode flags */ unsigned char c_line; /* line discipline */ unsigned char c_cc[NCC]; /* control characters */ }; |
このtermio構造体のメンバにローカル・モード・フラグ(c_lflag
)があ
るので、このフラグを構成しているECHOビットの部分を消せばエコーを禁止することができる。
このフラグ(c_lflag
)のビット構成(状態)は、通常、次のようになっている。
このままでは、どのビットを0にすれば、エコーを禁止できるのか分からない。
これは、ヘッダファイルの/usr/include/asm/termbits.hを見れば次のよ うに分かる。(次ページ参照)
/* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 #define XCASE 0000004 #define ECHO 0000010 <-- これ #define ECHOE 0000020 #define ECHOK 0000040 #define ECHONL 0000100 #define NOFLSH 0000200 #define TOSTOP 0000400 #define ECHOCTL 0001000 #define ECHOPRT 0002000 #define ECHOKE 0004000 #define FLUSHO 0010000 #define PENDIN 0040000 #define IEXTEN 0100000 |
ECHOのビット構成は次のようになっている。
このことから、ECHOビットの位置は、LSB(最下位のビット)から4ビット目であ ることが分かる。
そこで、このフラグ(c_lflag
)のLSBから4ビット目を0にすればよいことにな
る。
直感的には、c_lflag
からECHOを引き算すればよいが、一般に算術演算は
キャリーやオーバフローなどを考慮しなければならないので不適当である。
(ただし、今回の引き算に限っては大丈夫である。)
このようなばあい、通常は論理演算を行う。引き算に似た論理差を求める演算子
として排他的論理和(Exclusive OR)がある。C言語では排他的論理和のビット演算子と
して^
を使うので、次ような処理を行なえばよい。
c_lflag = c_lflag ^ ECHO;
C言語では、代入演算子とビット演算子を組み合わせた次のような表現も可能である。
c_lflag ^= ECHO;
なお、排他的論理和のビット演算子が無い言語を使うばあいは、ECHOを否定
(NOT)してc_lflag
との論理積(AND)をとればよい。否定されたECHOは
となるのでc_lflag
と論理積をとれば
c_lflag
のLSBから4ビット目を0にすることができる。排他的論理和に慣れ
ていないC言語プログラマーは、次のように、この方法を使うことが多い。
c_lflag &= ~ECHO;
さて、このようにしてECHOを禁止したプログラムを作成して実行すると、このま までは次のような動作結果になってしまう。
# ./pass Password: Password = boofoo
これは、パスワードを入力した最後の改行(New Line)もECHOが禁止されて しまうからである。その結果、パスワードの入力とパスワードの表示がつ ながってしまうことになる。
そこで、改行(New Line)だけはECHOを禁止しないことにする。 そのためには、次に示すエコーのニューライン(ECHONL)をセットすればよい。
/* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 #define XCASE 0000004 #define ECHO 0000010 #define ECHOE 0000020 #define ECHOK 0000040 #define ECHONL 0000100 <-- これ #define NOFLSH 0000200 #define TOSTOP 0000400 #define ECHOCTL 0001000 #define ECHOPRT 0002000 #define ECHOKE 0004000 #define FLUSHO 0010000 #define PENDIN 0040000 #define IEXTEN 0100000 |
ECHONLはLSBから7ビット目が1なので、これをc_lflag
にセットすればよ
い。そのためには、ECHONLとc_lflag
の論理和(OR)をとればよい。
C言語のビット演算子の論理和は|
なので、この処理は次のようにする。
c_lflag |= ECHONL;