09
5月
2007

termios

termiosは「非同期通信ポートを制御するための汎用ターミナルインタフェース」らしい.端末をclearしたりechoを抑制したり非カノニカルモードにしたりできる.
termios構造体
非カノニカルモード

termios構造体

termiosには,いろんな関数がある.これらの多くは,termios構造体を引数にとり,この構造体のフィールド操作によって端末を制御する.termios構造体は少なくとも以下のフィールドがある.
tcflags_t c_iflag
端末への入力をどうプログラムに渡すかの設定.
tcflags_t c_oflag
プログラムからの出力をどう処理するかの設定.
tcflags_t c_cflag
端末のハードウェア的制御の設定.
tcflags_t c_lflag
端末のいろんな制御の設定.
cc_t c_cc[NCCS]
特殊制御文字(EOFとか)の設定.
各フィールドの設定変更にはマクロを使用するが,沢山あるので随時manを見ることになりそうだ.端末制御のコーディングのパターンは以下のようになる.
tcgetattrで端末の現在の設定を取得.
端末の現在の設定のコピーを作成し,フィールドをいろいろ書き換える.
tcsetattrにあたらしい端末の設定を渡して反映.
何かする.
tcsetattrに最初に取得した端末の設定を渡して端末をもとの状態に戻す.
tcsetattrの第二引数には,端末設定の変更方法として以下の三つの選択肢がある.
TCSANOW
変更を即反映
TCSADRAIN
出力がすべて転送された後に反映.出力に影響するパラメータを変更したときに使用.
TCSAFLUSH
出力を全て転送し,受信したが読み込んでいない入力を全て破棄して反映.

非カノニカルモード

termiosについて詳細に書くのは大変なので例を書いてみる.通常は入力をいろいろ編集して納得したらリターンを押してプログラムに入力を渡す(カノニカルモード).が,キーを押した瞬間にプログラムに入力を渡したいこともある(非カノニカルモード).以下は非カノニカルモードで入力を受け取るサンプルである.

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>

void do_something(void);

int main(void)
{
  struct termios save_term;
  struct termios temp_term;

  /* ���ߤ�ü���������� */
  errno = 0;
  if(tcgetattr(fileno(stdin), &save_term) == -1){
    perror("tcgetattr failure");
    exit(EXIT_FAILURE);
  }else{
    temp_term = save_term;
  }

  /* ü������ */
  /* ��������CR��̵�� */
  temp_term.c_iflag &= IGNCR;
  /* ���Υ˥���⡼�ɤ򳰤� */
  temp_term.c_lflag &= ~ICANON;
  /* ���Ϥ򥨥������ʤ� */
  temp_term.c_lflag &= ~ECHO;
  /* �����ʥ��̵���� */
  temp_term.c_lflag &= ~ISIG;
  /* ��ʸ��������ä���read���֤뤫 */
  temp_term.c_cc[VMIN] = 1;
  /* ���÷Фä���read���֤뤫 */
  temp_term.c_cc[VTIME] = 0;

  errno = 0;
  if(tcsetattr(fileno(stdin), TCSANOW, &temp_term) == -1){
    perror("tcsetattr(temp_term) failure");
    exit(EXIT_FAILURE);
  }else{
    do_something();
  }

  /* ü��������Ȥ��᤹ */
  errno = 0;
  if(tcsetattr(fileno(stdin), TCSANOW, &save_term) == -1){
    perror("tcsetattr(save_term) failure");
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}

void do_something(void)
{
  char ch;

  while(ch != 'q'){
    ch = fgetc(stdin);
    /* ���Ϥ�CR��LF�ξ��ϲ��⤷�ʤ� */
    if(ch != '\r' && ch != '\n'){
      fprintf(stdout,"input = %c\n", ch);
    }
  }
}

実行結果を以下に示す.
$ ./nocanon
input = a
input = b
input = c
input = q
キーを押したら即input = ?と出て,エコーもない.

You may also like...