| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 1 | :mod:`pty` --- Pseudo-terminal utilities | 
 | 2 | ======================================== | 
 | 3 |  | 
 | 4 | .. module:: pty | 
| Benjamin Peterson | a0dfa82 | 2009-11-13 02:25:08 +0000 | [diff] [blame] | 5 |    :platform: Linux | 
 | 6 |    :synopsis: Pseudo-Terminal Handling for Linux. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 7 | .. moduleauthor:: Steen Lumholt | 
 | 8 | .. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il> | 
 | 9 |  | 
 | 10 |  | 
 | 11 | The :mod:`pty` module defines operations for handling the pseudo-terminal | 
 | 12 | concept: starting another process and being able to write to and read from its | 
 | 13 | controlling terminal programmatically. | 
 | 14 |  | 
| Mark Dickinson | 934896d | 2009-02-21 20:59:32 +0000 | [diff] [blame] | 15 | Because pseudo-terminal handling is highly platform dependent, there is code to | 
| Benjamin Peterson | a0dfa82 | 2009-11-13 02:25:08 +0000 | [diff] [blame] | 16 | do it only for Linux. (The Linux code is supposed to work on other platforms, | 
 | 17 | but hasn't been tested yet.) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 18 |  | 
 | 19 | The :mod:`pty` module defines the following functions: | 
 | 20 |  | 
 | 21 |  | 
 | 22 | .. function:: fork() | 
 | 23 |  | 
 | 24 |    Fork. Connect the child's controlling terminal to a pseudo-terminal. Return | 
 | 25 |    value is ``(pid, fd)``. Note that the child  gets *pid* 0, and the *fd* is | 
 | 26 |    *invalid*. The parent's return value is the *pid* of the child, and *fd* is a | 
 | 27 |    file descriptor connected to the child's controlling terminal (and also to the | 
 | 28 |    child's standard input and output). | 
 | 29 |  | 
 | 30 |  | 
 | 31 | .. function:: openpty() | 
 | 32 |  | 
 | 33 |    Open a new pseudo-terminal pair, using :func:`os.openpty` if possible, or | 
| Benjamin Peterson | a0dfa82 | 2009-11-13 02:25:08 +0000 | [diff] [blame] | 34 |    emulation code for generic Unix systems. Return a pair of file descriptors | 
 | 35 |    ``(master, slave)``, for the master and the slave end, respectively. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 36 |  | 
 | 37 |  | 
 | 38 | .. function:: spawn(argv[, master_read[, stdin_read]]) | 
 | 39 |  | 
 | 40 |    Spawn a process, and connect its controlling terminal with the current | 
 | 41 |    process's standard io. This is often used to baffle programs which insist on | 
 | 42 |    reading from the controlling terminal. | 
 | 43 |  | 
 | 44 |    The functions *master_read* and *stdin_read* should be functions which read from | 
| Georg Brandl | 9afde1c | 2007-11-01 20:32:30 +0000 | [diff] [blame] | 45 |    a file descriptor. The defaults try to read 1024 bytes each time they are | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 46 |    called. | 
 | 47 |  | 
| Gregory P. Smith | 0f21adf7 | 2012-09-29 12:41:03 -0700 | [diff] [blame] | 48 |    .. versionchanged:: 3.4 | 
 | 49 |       :func:`spawn` now returns the status value from :func:`os.waitpid` | 
 | 50 |       on the child process. | 
| Georg Brandl | 4cf83f4 | 2010-12-30 17:22:33 +0000 | [diff] [blame] | 51 |  | 
 | 52 | Example | 
 | 53 | ------- | 
 | 54 |  | 
 | 55 | .. sectionauthor:: Steen Lumholt | 
 | 56 |  | 
 | 57 | The following program acts like the Unix command :manpage:`script(1)`, using a | 
 | 58 | pseudo-terminal to record all input and output of a terminal session in a | 
 | 59 | "typescript". :: | 
 | 60 |  | 
 | 61 |    import sys, os, time, getopt | 
 | 62 |    import pty | 
 | 63 |  | 
 | 64 |    mode = 'wb' | 
 | 65 |    shell = 'sh' | 
 | 66 |    filename = 'typescript' | 
 | 67 |    if 'SHELL' in os.environ: | 
 | 68 |        shell = os.environ['SHELL'] | 
 | 69 |  | 
 | 70 |    try: | 
 | 71 |        opts, args = getopt.getopt(sys.argv[1:], 'ap') | 
 | 72 |    except getopt.error as msg: | 
 | 73 |        print('%s: %s' % (sys.argv[0], msg)) | 
 | 74 |        sys.exit(2) | 
 | 75 |  | 
 | 76 |    for opt, arg in opts: | 
 | 77 |        # option -a: append to typescript file | 
 | 78 |        if opt == '-a': | 
 | 79 |            mode = 'ab' | 
 | 80 |        # option -p: use a Python shell as the terminal command | 
 | 81 |        elif opt == '-p': | 
 | 82 |            shell = sys.executable | 
 | 83 |    if args: | 
 | 84 |        filename = args[0] | 
 | 85 |  | 
 | 86 |    script = open(filename, mode) | 
 | 87 |  | 
 | 88 |    def read(fd): | 
 | 89 |        data = os.read(fd, 1024) | 
 | 90 |        script.write(data) | 
 | 91 |        return data | 
 | 92 |  | 
 | 93 |    sys.stdout.write('Script started, file is %s\n' % filename) | 
 | 94 |    script.write(('Script started on %s\n' % time.asctime()).encode()) | 
 | 95 |    pty.spawn(shell, read) | 
 | 96 |    script.write(('Script done on %s\n' % time.asctime()).encode()) | 
 | 97 |    sys.stdout.write('Script done, file is %s\n' % filename) |