web-dev-qa-db-ja.com

`stty line NUMBER`は何をしているのですか?

this ページによると、このフィールドは、ユーザーがバックスペースまたは^ Cを押したときに何が起こるかを決定する「行の規律」を記述します。基本的に、プログラムがread(2)を呼び出すとどうなりますか。

ただし、設定しても効果がないようです。私のLinuxマシンには、2つのライン分野があります。

_$ cat /proc/tty/ldiscs
n_tty       0
n_null     27
_

しかし、_$ stty line 27_は何にも影響を与えていないようです。バックスペースは引き続き通常どおり機能します。

ただし、_$ stty -icanon_を実行すると、変更が表示されます---バックスペースが正常に機能しなくなり、プログラムは文字ごとに読み取ります(read(2)は常に1文字だけを返すようです)。

何が起きてる?

2
extremeaxe5

ラインディシプリンは、ttyドライバーとttyコアの間のレイヤーです(この図を参照してください、 ここ から): enter image description here

27(tty_null)に設定すると、日付は図の左側を通過します(行の規律をスキップします)。 0に設定すると、生の入力とcooked入力の両方を処理できるデフォルトの行規律が適用されます。

TTY(0)
    The default line discipline, providing transparent operation (raw mode)
    as well as the habitual terminal line editing capabilities (cooked mode).

他の分野のリストは ここ です。

独自に作成することも、既存のものを使用することもできます。 slipモジュールがあり、それをmodprobe slipに挿入すると、次のことに気付くでしょう。

$ cat /proc/tty/ldiscs 
n_tty       0
slip        1
n_null     27

$ stty line 27を実行すると、ラインディシプリンが削除され(ヌルラインディシプリンに設定されます)、$ stty -icanonを実行すると、rawモードでデフォルトのラインディシプリンが設定されます。

2

_stty line N_は何もしていません。

Linuxで行の規律を変更するには、 ioctl(TIOCSETD) を呼び出す必要がありますが、それは実行されません。 _stty line N_は、termios構造体の(非標準)_c_line_フィールドを変更し、tcsetattr(3)-> ioctl(TCSETS*)を呼び出すだけです。これにより、 _c_line_フィールドは後続のtcgetattr(3)-> ioctl(TCGETS)呼び出しによって返されます。

この回答の最後にあるのは小さなCのサンプルプログラムで、stdinfdの行の規律を実際に変更する必要があります。

stty(1)が不十分なのはこれだけではありません。 sttyは、「非標準」ボーレートを設定することもできません(これは、Linuxで_TCSETS2_/_TCSETSW2_/_TCSETSF2_ ioctlを使用して簡単に行うことができますが、残念ながら、標準Cライブラリには公開されておらず、sttyによって使用されていません。

_$ cat > tiocsetd.c <<'EOT'
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <err.h>

int main(int ac, char **av){
        int o;
        if(ioctl(0, TIOCGETD, &o)) err(1, "io(TIOCGETD)");
        if(ac > 1){
                int n, d = atoi(av[1]);
                if(ioctl(0, TIOCSETD, &d)) err(1, "io(TIOCSETD)");
                if(ioctl(0, TIOCGETD, &n)) err(1, "io(TIOCGETD)");
                printf("%d -> %d => %d\n", o, d, n);
        }else
                printf("%d\n", o);
        return 0;
}
EOT
$ cc -Wall tiocsetd.c -o tiocsetd
$ ./tiocsetd
0

$ tty
/dev/pts/4 ## << make a note of this
$ cat /proc/tty/ldiscs
n_tty       0
n_null     27
$ ./tiocsetd 27
<your tty is hugged ;-)>
_

復元するには、別の端末から_./tiocsetd 0 </dev/pts/4_を実行し(_/dev/pts/4_を実際のttyに置き換えます)、_^C_を押します。

2
mosvy