UDP/IP、端末

システム・プログラムI

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1997/1997-06-24
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html

■復習

■echo-client-udp

■echo-server-udp

■termio

UNIX では、端末から受け取った文字を加工してプログラムに渡している。こ のため、どんなプログラムでも^HDelete で1文字削 除できたり、行ごとの削除ができたりする。エディタのプログラムを作る時に は、このような動きを抑えたい。また、more, less などのようなプログラム を作る時には、1文字単位で入力したい。これを実現するためには、 tcsetattr() を用いる。

----------------------------------------------------------------------
   1:	/*
   2:	        term-cbreak.c -- 端末から文字単位で入力する
   3:	        /usr/local/LECTURES/syspro-1997-shinjo/term/term-cbreak.c
   4:	        $Header: term-cbreak.c,v 1.2 97/06/23 22:43:32 yas Exp $
   5:	        Start: 1997/06/23 22:26:31
   6:	*/
   7:	
   8:	#include <stdio.h>      /* stderr */
   9:	#include <termios.h>    /* struct termios */
  10:	
  11:	main( argc,argv )
  12:	    int argc ;
  13:	    char *argv[] ;
  14:	{
  15:	    struct termios tattr, tattr_save ;
  16:	
  17:	        if( ! isatty(0) )
  18:	        {
  19:	            fprintf(stderr,"stdin is not tty\n");
  20:	            exit( 1 );
  21:	        }
  22:	        if( tcgetattr( 0, &tattr ) < 0 )
  23:	        {
  24:	            perror("tcgetattr");
  25:	            exit( 1 );
  26:	        }
  27:	        tattr_save = tattr ;
  28:	
  29:	        tattr.c_iflag &= ~(BRKINT|ISTRIP|IXON);
  30:	        tattr.c_lflag &= ~(ICANON|IEXTEN);
  31:	        tattr.c_cc[VMIN] = 1 ;
  32:	        tattr.c_cc[VTIME] = 0 ;
  33:	        if( tcsetattr( 0, TCSANOW, &tattr )<0 )
  34:	        {
  35:	            perror("tcsetattr");
  36:	            exit( 1 );
  37:	        }
  38:	
  39:	        getputchar();
  40:	
  41:	        if( tcsetattr( 0,TCSANOW, &tattr_save ) < 0 )
  42:	        {
  43:	            perror("tcsetattr");
  44:	            exit( 1 );
  45:	        }
  46:	}
  47:	
  48:	getputchar()
  49:	{
  50:	    int c ;
  51:	        while( (c=getchar()) > 0 )
  52:	        {
  53:	            putchar( c );
  54:	            if( c == 'q' )
  55:	                break;
  56:	        }
  57:	}
----------------------------------------------------------------------

実行例。


----------------------------------------------------------------------
% ../file/stdio-thru  [←]
abc[←]
abc
q[←]
q
^D
% ./term-cbreak [←]
aabbcc[←]

qq% [←]
% []
----------------------------------------------------------------------

エコーバックを抑止するには、c_iflag の ECHO, ECHOK, ECHOKE などのビッ トも落とす(c_flag &=~(...))。割り込みも効かないようにする には、ISIG を落とす。

出力の処理(CRをCR,LNに変換)などの処理を抑止するには、 c_oflag で OPOST ビットを落とす。

くわしくは、man termio 。

★練習問題(43) getpass()の実現

getpass() ライブラリ関数と似た動きをする関数を作りなさい。 (getpass() は、/dev/tty を開いている。moreやlessも、標準入力ではなく、 このファイルを開き、コマンドのキーを読み込む。)

■terminfo


----------------------------------------------------------------------
   1:	/*
   2:	        term-rev.c -- 反転で出力する
   3:	        /usr/local/LECTURES/syspro-1997-shinjo/term/term-rev.c
   4:	        $Header: term-rev.c,v 1.1 97/06/23 23:19:00 yas Exp $
   5:	        Start: 1997/06/23 22:26:31
   6:	*/
   7:	main()
   8:	{
   9:	        printf("012");
  10:	        putchar( 0x1b );putchar('[');putchar('7');putchar('m');
  11:	        printf("345");
  12:	        putchar( 0x1b );putchar('[');putchar('m');
  13:	        printf("678\n");
  14:	}
----------------------------------------------------------------------

実行例。

123[反転]456[反転終わり]789

ESC (0x1b) [ 7 m を出力した後は、反転する。 ESC (0x1b) [ mを出力した後は、もとにもどる。 このように、端末の状態を変えるための 文字を、エスケープ・シーケンス(Escape sequence)という。

この方法は、端末の種類によってことなる。どの端末でも働くようなプログラ ムを作るには、terminfo ライブラリ(または termcap ライブラリ)を使う。こ れは、ファイルに保存されているエスケープ・シーケンスを利用するためのラ イブラリ関数である。


----------------------------------------------------------------------
% ls /usr/lib/terminfo/v/vt100 [←]
/usr/lib/terminfo/v/vt100
% ls /usr/lib/terminfo/k/kterm [←]
/usr/lib/terminfo/k/kterm
% ls /usr/lib/terminfo/h/hpterm [←]
/usr/lib/terminfo/h/hpterm
% []
----------------------------------------------------------------------

----------------------------------------------------------------------
   1:	/*
   2:	        term-rev-info.c -- 反転で出力する(terminfoを使う)
   3:	        「cc term-rev-info.c -o term-rev-info -lcurses」でコンパイル
   4:	        /usr/local/LECTURES/syspro-1997-shinjo/term/term-rev.c
   5:	        $Header: term-rev-info.c,v 1.2 97/06/23 23:50:30 yas Exp $
   6:	        Start: 1997/06/23 22:26:31
   7:	*/
   8:	#include <stdio.h>
   9:	#include <curses.h>
  10:	#include <term.h>
  11:	
  12:	main()
  13:	{
  14:	        setupterm(NULL, 1, NULL);
  15:	        putp("012");
  16:	        putp(enter_reverse_mode);
  17:	        putp("345");
  18:	        putp(exit_attribute_mode);
  19:	        putp("678\n");
  20:	}
----------------------------------------------------------------------

コンパイルと実行。リンクには、-lcursesを付ける。

123[反転]456[反転終わり]789

★練習問題(44) 下線

反転させるのではなく、下線を付けてみなさい。

■cursesライブラリ

cursesでは、文字端末で動作する画面指向のアプリケーションを開発するため のライブラリです。cursesでは、画面を直接操作するのではなく、内部的なバッ ファを操作することになります。そして、このバッファは、refresh() が呼ば れてはじめて表示されます。このとき、前に refresh() を呼び出した時との 差分だけが自動的に出力されます。

詳しくは、man curses。

★練習問題(45) cursesライブラリの利用

反転、あるいは、下線を付けるプログラムを、cursesライブラリを利用して実 現して見なさい。

★[report] report-9,TCP/IPのサーバ(締切7月4日)

練習問題(36),(39),(40),(42) の中から1つ以上選んでやりなさい。問題を難 しい方に変更してもよい。 (注意:6月10の印刷資料には、(36) ではなくて、(37)になっていました。 )

締切は、7月4日とします。


↑[もどる] ←[6月17日] ・[6月24日]
Last updated: 1997/06/24 00:15:08
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>