"pty" --- 擬似端末ユーティリティ
********************************

**ソースコード:** Lib/pty.py

======================================================================

"pty" モジュールは、別のプロセスを起動してその制御端末をプログラムから
読み書きする、擬似端末の操作を定義します。

利用可能な環境: Unix.

擬似端末の扱いはプラットフォームに大きく依存します。 このコードは主に
Linux、FreeBSD、macOS でテストされています (他の POSIX プラットフォー
ムでも動作するはずですが、十分にはテストされていません)。

"pty" モジュールは次の関数を定義しています。

pty.fork()

   forkします。 子プロセスの制御端末を擬似端末に接続します。 返り値は
   "(pid, fd)" です。 子プロセスでは *pid* は 0 で、*fd* は *無効* で
   す。 親プロセスは *pid* として子プロセスのPID、*fd* として子プロセ
   スの制御端末 (子プロセスの標準入出力に接続されている)のファイル記述
   子を受けとります。

   返されるファイル記述子 *fd* は 継承不可 です。

   警告:

     macOS では、"urllib.request" を含む高水準のシステム API と併用す
     ると、この関数の使用は安全ではありません。

   バージョン 3.15 で変更: 返されるファイル記述子が継承不可になりまし
   た。

pty.openpty()

   新しい擬似端末のペアを開きます。利用できるなら "os.openpty()" を使
   い、利用できなければ一般的なUnixシステム用のエミュレーションコード
   を使います。マスター、スレーブそれぞれのためのファイル記述子、
   "(master, slave)" のタプルを返します。

pty.spawn(argv[, master_read[, stdin_read]])

   プロセスを起動し、その制御端末を現在のプロセスの標準入出力に接続し
   ます。 制御端末からしか入力を読み込まないプログラムに、別の方法で入
   力を渡すためによく使います。 擬似端末を使って起動したプロセスは最終
   的に終了することが想定されており、終了すると *spawn* が戻ります。

   ループ処理によって、現在のプロセスの STDIN を子プロセスに、子プロセ
   スから受け取ったデータを現在のプロセスの STDOUT にコピーします。 現
   在のプロセスの STDIN が閉じられても、そのことは子プロセスに通知され
   ません。

   The functions *master_read* and *stdin_read* are passed a file
   descriptor which they should read from, and they should always
   return a byte string. In order to force spawn to return before the
   child process exits an empty byte array should be returned to
   signal end of file.

   どちらの関数も、デフォルトの実装は呼び出しごとに最大 1024 バイトを
   読み込んで返します。 *master_read* コールバックには、子プロセスの出
   力を読み込むために擬似端末のマスター側のファイル記述子が渡されます
   。 *stdin_read* には、親プロセスの標準入力を読み込むためにファイル
   記述子 0 が渡されます。

   Returning an empty byte string from either callback is interpreted
   as an end-of-file (EOF) condition, and that callback will not be
   called after that. If *stdin_read* signals EOF the controlling
   terminal can no longer communicate with the parent process OR the
   child process. Unless the child process will quit without any
   input, *spawn* will then loop forever. If *master_read* signals EOF
   the same behavior results (on linux at least).

   子プロセスに対する "os.waitpid()" の終了ステータス値を返します。

   "os.waitstatus_to_exitcode()" で終了ステータスを終了コードに変換で
   きます。

   引数 "argv" を指定して 監査イベント "pty.spawn" を送出します。

   バージョン 3.4 で変更: "spawn()" が "os.waitpid()" が返す子プロセス
   のステータス値を返すようになりました。


使用例
======

下記のプログラムは Unix コマンド *script(1)* のように動作します。疑似
端末を使用して、端末セッションのすべての入出力を "typescript" に記録し
ます。

   import argparse
   import os
   import pty
   import sys
   import time

   parser = argparse.ArgumentParser()
   parser.add_argument('-a', dest='append', action='store_true')
   parser.add_argument('-p', dest='use_python', action='store_true')
   parser.add_argument('filename', nargs='?', default='typescript')
   options = parser.parse_args()

   shell = sys.executable if options.use_python else os.environ.get('SHELL', 'sh')
   filename = options.filename
   mode = 'ab' if options.append else 'wb'

   with open(filename, mode) as script:
       def read(fd):
           data = os.read(fd, 1024)
           script.write(data)
           return data

       print('Script started, file is', filename)
       script.write(('Script started on %s\n' % time.asctime()).encode())

       pty.spawn(shell, read)

       script.write(('Script done on %s\n' % time.asctime()).encode())
       print('Script done, file is', filename)
