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 = ?と出て,エコーもない.