1 | # |
---|
2 | # Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved |
---|
3 | # |
---|
4 | # PSF LICENSE AGREEMENT FOR PYTHON 2.3 |
---|
5 | # ------------------------------------ |
---|
6 | # |
---|
7 | # 1. This LICENSE AGREEMENT is between the Python Software Foundation |
---|
8 | # ("PSF"), and the Individual or Organization ("Licensee") accessing and |
---|
9 | # otherwise using Python 2.3 software in source or binary form and its |
---|
10 | # associated documentation. |
---|
11 | # |
---|
12 | # 2. Subject to the terms and conditions of this License Agreement, PSF |
---|
13 | # hereby grants Licensee a nonexclusive, royalty-free, world-wide |
---|
14 | # license to reproduce, analyze, test, perform and/or display publicly, |
---|
15 | # prepare derivative works, distribute, and otherwise use Python 2.3 |
---|
16 | # alone or in any derivative version, provided, however, that PSF's |
---|
17 | # License Agreement and PSF's notice of copyright, i.e., "Copyright (c) |
---|
18 | # 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" are |
---|
19 | # retained in Python 2.3 alone or in any derivative version prepared by |
---|
20 | # Licensee. |
---|
21 | # |
---|
22 | # 3. In the event Licensee prepares a derivative work that is based on |
---|
23 | # or incorporates Python 2.3 or any part thereof, and wants to make |
---|
24 | # the derivative work available to others as provided herein, then |
---|
25 | # Licensee hereby agrees to include in any such work a brief summary of |
---|
26 | # the changes made to Python 2.3. |
---|
27 | # |
---|
28 | # 4. PSF is making Python 2.3 available to Licensee on an "AS IS" |
---|
29 | # basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR |
---|
30 | # IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND |
---|
31 | # DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS |
---|
32 | # FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT |
---|
33 | # INFRINGE ANY THIRD PARTY RIGHTS. |
---|
34 | # |
---|
35 | # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON |
---|
36 | # 2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS |
---|
37 | # A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3, |
---|
38 | # OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. |
---|
39 | # |
---|
40 | # 6. This License Agreement will automatically terminate upon a material |
---|
41 | # breach of its terms and conditions. |
---|
42 | # |
---|
43 | # 7. Nothing in this License Agreement shall be deemed to create any |
---|
44 | # relationship of agency, partnership, or joint venture between PSF and |
---|
45 | # Licensee. This License Agreement does not grant permission to use PSF |
---|
46 | # trademarks or trade name in a trademark sense to endorse or promote |
---|
47 | # products or services of Licensee, or any third party. |
---|
48 | # |
---|
49 | # 8. By copying, installing or otherwise using Python 2.3, Licensee |
---|
50 | # agrees to be bound by the terms and conditions of this License |
---|
51 | # Agreement. |
---|
52 | # |
---|
53 | # Modifications: Copyright (c) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk> |
---|
54 | # - add support for excluding a list of file descriptors from being |
---|
55 | # closed, allowing access to those file descriptors from the command. |
---|
56 | # |
---|
57 | |
---|
58 | """Spawn a command with pipes to its stdin, stdout, and optionally stderr. |
---|
59 | |
---|
60 | The normal os.popen(cmd, mode) call spawns a shell command and provides a |
---|
61 | file interface to just the input or output of the process depending on |
---|
62 | whether mode is 'r' or 'w'. This module provides the functions xpopen2(cmd) |
---|
63 | and xpopen3(cmd) which return two or three pipes to the spawned command. |
---|
64 | Optionally exclude a list of file descriptors from being closed, allowing |
---|
65 | access to those file descriptors from the command. |
---|
66 | """ |
---|
67 | |
---|
68 | import os |
---|
69 | import sys |
---|
70 | |
---|
71 | try: |
---|
72 | MAXFD = os.sysconf('SC_OPEN_MAX') |
---|
73 | except (AttributeError, ValueError): |
---|
74 | MAXFD = 256 |
---|
75 | |
---|
76 | _active = [] |
---|
77 | |
---|
78 | def _cleanup(): |
---|
79 | for inst in _active[:]: |
---|
80 | inst.poll() |
---|
81 | |
---|
82 | class xPopen3: |
---|
83 | """Class representing a child process. Normally instances are created |
---|
84 | by the factory functions popen2() and popen3().""" |
---|
85 | |
---|
86 | sts = -1 # Child not completed yet |
---|
87 | |
---|
88 | def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=()): |
---|
89 | """The parameter 'cmd' is the shell command to execute in a |
---|
90 | sub-process. The 'capturestderr' flag, if true, specifies that |
---|
91 | the object should capture standard error output of the child process. |
---|
92 | The default is false. If the 'bufsize' parameter is specified, it |
---|
93 | specifies the size of the I/O buffers to/from the child process.""" |
---|
94 | _cleanup() |
---|
95 | self.passfd = passfd |
---|
96 | p2cread, p2cwrite = os.pipe() |
---|
97 | c2pread, c2pwrite = os.pipe() |
---|
98 | if capturestderr: |
---|
99 | errout, errin = os.pipe() |
---|
100 | self.pid = os.fork() |
---|
101 | if self.pid == 0: |
---|
102 | # Child |
---|
103 | os.dup2(p2cread, 0) |
---|
104 | os.dup2(c2pwrite, 1) |
---|
105 | if capturestderr: |
---|
106 | os.dup2(errin, 2) |
---|
107 | self._run_child(cmd) |
---|
108 | os.close(p2cread) |
---|
109 | self.tochild = os.fdopen(p2cwrite, 'w', bufsize) |
---|
110 | os.close(c2pwrite) |
---|
111 | self.fromchild = os.fdopen(c2pread, 'r', bufsize) |
---|
112 | if capturestderr: |
---|
113 | os.close(errin) |
---|
114 | self.childerr = os.fdopen(errout, 'r', bufsize) |
---|
115 | else: |
---|
116 | self.childerr = None |
---|
117 | _active.append(self) |
---|
118 | |
---|
119 | def _run_child(self, cmd): |
---|
120 | if isinstance(cmd, basestring): |
---|
121 | cmd = ['/bin/sh', '-c', cmd] |
---|
122 | for i in range(3, MAXFD): |
---|
123 | if i in self.passfd: |
---|
124 | continue |
---|
125 | try: |
---|
126 | os.close(i) |
---|
127 | except OSError: |
---|
128 | pass |
---|
129 | try: |
---|
130 | os.execvp(cmd[0], cmd) |
---|
131 | finally: |
---|
132 | os._exit(127) |
---|
133 | |
---|
134 | def poll(self): |
---|
135 | """Return the exit status of the child process if it has finished, |
---|
136 | or -1 if it hasn't finished yet.""" |
---|
137 | if self.sts < 0: |
---|
138 | try: |
---|
139 | pid, sts = os.waitpid(self.pid, os.WNOHANG) |
---|
140 | if pid == self.pid: |
---|
141 | self.sts = sts |
---|
142 | _active.remove(self) |
---|
143 | except os.error: |
---|
144 | pass |
---|
145 | return self.sts |
---|
146 | |
---|
147 | def wait(self): |
---|
148 | """Wait for and return the exit status of the child process.""" |
---|
149 | if self.sts < 0: |
---|
150 | pid, sts = os.waitpid(self.pid, 0) |
---|
151 | if pid == self.pid: |
---|
152 | self.sts = sts |
---|
153 | _active.remove(self) |
---|
154 | return self.sts |
---|
155 | |
---|
156 | |
---|
157 | def xpopen2(cmd, bufsize=-1, mode='t', passfd=[]): |
---|
158 | """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is |
---|
159 | specified, it sets the buffer size for the I/O pipes. The file objects |
---|
160 | (child_stdout, child_stdin) are returned.""" |
---|
161 | inst = xPopen3(cmd, False, bufsize, passfd) |
---|
162 | return inst.fromchild, inst.tochild |
---|
163 | |
---|
164 | def xpopen3(cmd, bufsize=-1, mode='t', passfd=[]): |
---|
165 | """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is |
---|
166 | specified, it sets the buffer size for the I/O pipes. The file objects |
---|
167 | (child_stdout, child_stdin, child_stderr) are returned.""" |
---|
168 | inst = xPopen3(cmd, True, bufsize, passfd) |
---|
169 | return inst.fromchild, inst.tochild, inst.childerr |
---|