"pty" --- Utilidades para Pseudo-terminal
*****************************************

**Código Fuente:** Lib/pty.py

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

El módulo "pty" define las operaciones para manejar el concepto de
pseudo-terminal: iniciar otro proceso para poder escribir y leer desde
su propia terminal mediante programación.

Debido a que el manejo de una pseudo-terminal depende en gran medida
de la plataforma, este código es solo para Linux (se supone que el
código de Linux funciona para otras plataformas, pero este aún no se
ha probado)

El modulo "pty" define las siguientes funciones:

pty.fork()

   Bifurcación. Conectar en su propia terminal (terminal hijo) una
   pseudo-terminal. El valor de retorno es "(pid, fd)". Tener en
   cuenta que la terminal hijo tiene como valor *pid* 0 y *fd* es
   *invalid*. El valor de retorno del padre es el *pid* del hijo, y
   *fd* es un descriptor de archivo conectado a la terminal hijo
   (también a la salida y entrada estándar de la terminal hijo)

pty.openpty()

   Abre un nuevo par de pseudo-terminales, usando "os.openpty()", o
   código de emulación para sistemas genéricos de Unix. Retorna un par
   de descriptores de archivo "(master, slave)", para el *master* y el
   *slave* respectivamente.

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

   Genera un proceso conectado a su terminal con el io estándar del
   proceso actual. Esto se usa a frecuentemente para confundir
   programas que insisten en leer desde la terminal de control. Se
   espera que el proceso generado detrás de pty sea finalizado y
   cuando lo haga *spawn* se retornará.

   Las funciones *master_read* y *stdin_read* se les envía como
   parámetro un descriptor de archivo y siempre deben retornar una
   cadena de bytes. A fin de que se obligue a *spawn* a retornar antes
   que el proceso hijo salga se debe lanzar un "OSError".

   La implementación predeterminada para ambas funciones retornará
   hasta 1024 bytes cada vez que se llamen. El dato retornado de
   *master_read* se pasa al descriptor de archivo maestro para leer la
   salida del proceso hijo, y *stdin_read* pasa el descriptor de
   archivo 0, para leer desde la entrada del proceso padre.

   Retornando una cadena de bytes vacía de cualquier llamado es
   interpretado como una condición de fin de archivo (EOF), y el
   llamado no se realizará después de eso. Si *stdin_read* retorna EOF
   la terminal de control ya no puede comunicarse con el proceso padre
   o el proceso hijo. A menos que el proceso hijo se cierre sin
   ninguna entrada *spawn* se repetirá para siempre. Si *master_read*
   retorna EOF se produce el mismo comportamiento (al menos en Linux)

   Si ambas retrollamadas retornan EOF entonces  *spawn* probablemente
   nunca retorne algo, a menos que *select* entregue un error en su
   plataforma cuando pasan tres listas vacías. Esto es un error
   documentado en issue 26228.

   Retorna el valor del estado de salida de "os.waitpid()" en el
   proceso hijo.

   "waitstatus_to_exitcode()" se puede utilizar para convertir el
   estado de salida en un código de salida.

   Lanza un evento de auditoria "pty.spawn"  con el argumento "argv".

   Distinto en la versión 3.4: "spawn()" ahora retorna el valor de
   estado de  "os.waitpid()" para los procesos hijos.


Ejemplo
=======

El siguiente programa actúa como el comando de Unix *script(1)*,
usando una pseudo-terminal para registrar todas las entradas y salidas
de una sesión en "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)
