_/dev/ptmx
_からの単純なシェルリダイレクトにより、新しい疑似端末が得られるようです。
_$ ls /dev/pts; ls /dev/pts </dev/ptmx
0 1 2 ptmx
0 1 2 3 ptmx
_
_/dev/ptmx
_のfdクレームを所有するプロセスが終了するとすぐに消えますが、それを保持するのに十分簡単です。
_$ PS1='<$(ls -1 "$@" /dev/pts/*|uniq -u)> $ ' \
exec 3<>/dev/ptmx "$0" -si -- /dev/pts/*
</dev/pts/3> $ ls /dev/pts; exec 3>&-
0 1 2 3 ptmx
<> $ ls /dev/pts; exec 3<>/dev/ptmx
0 1 2 ptmx
</dev/pts/3> $ exit
_
したがって、疑似端末を取得するには、_/dev/ptmx
_の単純なopen()
で十分であるように見えます。私はそれがシェルを作るだろうと思います-(またはそれがリダイレクトを行うプロセス)-ptyのマスター側の所有者。
しかし、どのようにスレーブ側を割り当てるのですか?またはcanスレーブ側を割り当てますか?そして、私ができるなら-私はそれで何ができますか? stty
を使用して、読み取り/書き込み/フラッシュのタイミングに影響を与えることはできますか? _/dev/tty
_を参照するときに、スレーブ側のプロセスは新しいptyにリンクしますか?
したがって、@ muruがコメントで指摘しているように、作成されたptyをシェルだけでインターフェースする簡単な方法はないようです。 unlockpt()
部分以外はすべて管理しました。私が読んだものによると ここ 新しく作成されたptyロックを無効にするためのコンパイル時オプションがカーネルにあるかもしれませんが、私はそれをしたくありませんでした。それで、私は何か他のことをしました。
実際にはgrantpt()
は必要ありませんでした。見つかった説明によると ここ _/dev/pts/[num]
_デバイスファイルのUID/GIDを変更するだけです。しかし、_man mount
_によると、それを処理する簡単な方法があります。 devpts
マウントオプションは次のとおりです。
uid=value
_および_gid=value
_ gid=5
_により、新しく作成されたPTYはttyグループ。それは私のシステムではすでにデフォルトで当てはまりました。しかし、それを読んだ後、私は結局変更を加えたいと思うかもしれないことに気づきました。次のセクションは次のとおりです。
ptmxmode=value
_ devpts
ファイルシステムで新しいptmxデバイスノードのモードを設定します。devpts
の複数のインスタンスのサポート(上記のnewinstance
オプションを参照)により、各インスタンスには、devpts
ファイルシステムのルートにプライベートptmxノードがあります(通常は_/dev/pts/ptmx
_)。0000
_です。 _ptmxmode=value
_は、ptmxノードのより便利なモードを指定し、newinstance
オプションが指定されている場合に強くお勧めします。そうしなくても機能するはずでしたが、私はそのアイデアが気に入り、 カーネルドキュメント で推奨されているように_0640
_に設定しました。ちなみに、カーネルドキュメントリンクでは、newinstance
マウントオプションについて詳しく説明しています。これは非常に優れており、基本的に、_/dev/ptmx
_マウントごとに名前を空けたptyのグループを個別に取得できます。
とにかく、何か他のものは主に次のようになりました:
_mount -o remount,newinstance,gid=5,ptmxmode=0640 /dev/pts
mount --bind /dev/pts/ptmx /dev/ptmx
_
...カーネルドキュメントが推奨するように-理由についてのリンクを参照してください。また、_/etc/fstab
_に数行追加することで、上記のコマンドの効果を永続的にしました。
そして...
_<<\C cc -xc - -o pts
#include <stdio.h>
int main(int argc, char *argv[]) {
if(unlockpt(0)) return 2;
char *ptsname(int fd);
printf("%s\n",ptsname(0));
return argc - 1;
}
C
_
これは、stdinでunlockpt()
を呼び出そうとする小さなCプログラムをコンパイルし、成功すると、新しく作成されロック解除されたptyの名前をstdout
に出力するか、サイレントに2を返します。
それが完了すると、次のような独自のscreenedプロセスを作成できます。
_exec 3<>/dev/ptmx
_
...現在のシェルでマスター側のfdを取得するには...
_(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &
_
これにより、バックグラウンドで疑似端末のもう一方の端でインタラクティブシェルが実行されます。 _>&3
_に出力されたものはすべてユーザー入力として解釈されます。
_mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$
_
これは基本的に、バックグラウンドでログに記録されたインタラクティブなインタプリタ(またはこれらで実行したい他の何か)ala screen
を、それほどオーバーヘッドなしで、ファイル上でネットします。私が選んだ記述子。
現在のシェルが所有するマスター側のfdは、スレーブ側の入力を提供する唯一の手段であり、現在のシェルプロセス(およびその子)によってのみ書き込み可能です。 _>&3
_に書き込むことで相手と通信でき、必要に応じて同じファイルまたはログファイルから読み取ることができます。
そして、stty
は結局ターミナルで機能します:
_mikeserv@localhost$ echo stty -a ">$(tty)" >&3
speed 38400 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc
-ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl
echoke
_