next up previous
次へ: ioctlのコマンドcmd 上へ: ioctlを使ったプログラム 戻る: ioctlを使ったプログラム

ローカル・モード・フラグ

ターミナルを制御するばあいは、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)のビット構成(状態)は、通常、次のようになっている。

$105073_{8} = 1 000 101 000 111 011_{2}$

このままでは、どのビットを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のビット構成は次のようになっている。

$0000010_{8} => 0 000 000 000 001 000_{2}$

このことから、ECHOビットの位置は、LSB(最下位のビット)から4ビット目であ ることが分かる。

そこで、このフラグ(c_lflag)のLSBから4ビット目を0にすればよいことにな る。

$1 000 101 000 111 011_{2}$
$0 000 000 000 001 000_{2}$

直感的には、c_lflagからECHOを引き算すればよいが、一般に算術演算は キャリーやオーバフローなどを考慮しなければならないので不適当である。 (ただし、今回の引き算に限っては大丈夫である。)

このようなばあい、通常は論理演算を行う。引き算に似た論理差を求める演算子 として排他的論理和(Exclusive OR)がある。C言語では排他的論理和のビット演算子と して^を使うので、次ような処理を行なえばよい。

    c_lflag = c_lflag ^ ECHO;

C言語では、代入演算子とビット演算子を組み合わせた次のような表現も可能である。

    c_lflag ^= ECHO;

なお、排他的論理和のビット演算子が無い言語を使うばあいは、ECHOを否定 (NOT)してc_lflagとの論理積(AND)をとればよい。否定されたECHO $1 111 111 111 110 111_{2}$となるので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にセットすればよ い。そのためには、ECHONLc_lflagの論理和(OR)をとればよい。 C言語のビット演算子の論理和は|なので、この処理は次のようにする。

    c_lflag |= ECHONL;



MANOME Yoichi 平成19年1月6日