12 |
12 |
13 PIPE = "42" |
13 PIPE = "42" |
14 |
14 |
15 |
15 |
16 class Popen(object): |
16 class Popen(object): |
17 def __init__(self, args, stdin=None, stdout=None): |
17 def __init__(self, args, stdin=None, stdout=None, stderr=None): |
18 self.returncode = None |
18 self.returncode = None |
19 self.stdout = None |
19 self.stdout = None |
|
20 self.stderr = None |
20 self.stdin = None |
21 self.stdin = None |
21 # TODO: stderr |
|
22 file_actions = posix_spawn.FileActions() |
22 file_actions = posix_spawn.FileActions() |
23 if stdout is not None: |
23 if stdout is not None: |
24 # child's stdout, child 2 parent pipe |
24 # child's stdout, child 2 parent pipe |
|
25 c1pread, c1pwrite = os.pipe() |
|
26 # attach child's stdout to writing en of c1p pipe |
|
27 file_actions.add_dup2(c1pwrite, 1) |
|
28 # close other end |
|
29 file_actions.add_close(c1pread) |
|
30 if stderr is not None: |
|
31 # child's stderr, child 2 parent pipe |
25 c2pread, c2pwrite = os.pipe() |
32 c2pread, c2pwrite = os.pipe() |
26 # attach child's stdout to writing en of c2p pipe |
33 # attach child's stderr to writing en of c2p pipe |
27 file_actions.add_dup2(c2pwrite, 1) |
34 file_actions.add_dup2(c2pwrite, 2) |
28 # close other end |
35 # close other end |
29 file_actions.add_close(c2pread) |
36 file_actions.add_close(c2pread) |
30 if stdin is not None: |
37 if stdin is not None: |
31 # child's stdin, parent to child pipe |
38 # child's stdin, parent to child pipe |
32 p2cread, p2cwrite = os.pipe() |
39 p2cread, p2cwrite = os.pipe() |
34 file_actions.add_dup2(p2cread, 0) |
41 file_actions.add_dup2(p2cread, 0) |
35 # close other end |
42 # close other end |
36 file_actions.add_close(p2cwrite) |
43 file_actions.add_close(p2cwrite) |
37 self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions) |
44 self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions) |
38 if stdout is not None: |
45 if stdout is not None: |
39 self.stdout = os.fdopen(c2pread) |
46 self.stdout = os.fdopen(c1pread) |
|
47 os.close(c1pwrite) |
|
48 if stderr is not None: |
|
49 self.stderr = os.fdopen(c2pread) |
40 os.close(c2pwrite) |
50 os.close(c2pwrite) |
41 if stdin is not None: |
51 if stdin is not None: |
42 self.stdin = os.fdopen(p2cwrite, 'w') |
52 self.stdin = os.fdopen(p2cwrite, 'w') |
43 os.close(p2cread) |
53 os.close(p2cread) |
44 |
54 |
48 |
58 |
49 def communicate(self): |
59 def communicate(self): |
50 if self.stdin is not None: |
60 if self.stdin is not None: |
51 self.stdin.close() |
61 self.stdin.close() |
52 self.stdin = None |
62 self.stdin = None |
|
63 |
53 if self.stdout is not None: |
64 if self.stdout is not None: |
54 stdoutdata = self.stdout.read() |
65 stdoutdata = self.stdout.read() |
55 else: |
66 else: |
56 stdoutdata = "" |
67 stdoutdata = "" |
57 |
68 |
58 # TODO |
69 if self.stderr is not None: |
59 stderrdata = "" |
70 stderrdata = self.stderr.read() |
|
71 else: |
|
72 stderrdata = "" |
60 |
73 |
61 self._wait() |
74 self._wait() |
|
75 |
62 if self.stdout is not None: |
76 if self.stdout is not None: |
63 self.stdout.close() |
77 self.stdout.close() |
64 self.stdout = None |
78 self.stdout = None |
|
79 |
|
80 if self.stderr is not None: |
|
81 self.stderr.close() |
|
82 self.stderr = None |
65 |
83 |
66 return (stdoutdata, stderrdata) |
84 return (stdoutdata, stderrdata) |
67 |
85 |
68 def wait(self): |
86 def wait(self): |
69 if self.stdin is not None: |
87 if self.stdin is not None: |
70 self.stdin.close() |
88 self.stdin.close() |
71 self.stdin = None |
89 self.stdin = None |
|
90 |
72 self._wait() |
91 self._wait() |
|
92 |
73 if self.stdout is not None: |
93 if self.stdout is not None: |
74 self.stdout.close() |
94 self.stdout.close() |
75 self.stdout = None |
95 self.stdout = None |
|
96 |
|
97 if self.stderr is not None: |
|
98 self.stderr.close() |
|
99 self.stderr = None |
|
100 |
76 return self.returncode |
101 return self.returncode |
77 |
102 |
78 def poll(self): |
103 def poll(self): |
79 if self.returncode is None: |
104 if self.returncode is None: |
80 pid, ret = os.waitpid(self.pid, os.WNOHANG) |
105 pid, ret = os.waitpid(self.pid, os.WNOHANG) |
82 self.returncode = ret |
107 self.returncode = ret |
83 |
108 |
84 if self.stdin is not None: |
109 if self.stdin is not None: |
85 self.stdin.close() |
110 self.stdin.close() |
86 self.stdin = None |
111 self.stdin = None |
|
112 |
87 if self.stdout is not None: |
113 if self.stdout is not None: |
88 self.stdout.close() |
114 self.stdout.close() |
89 self.stdout = None |
115 self.stdout = None |
|
116 |
|
117 if self.stderr is not None: |
|
118 self.stderr.close() |
|
119 self.stderr = None |
90 |
120 |
91 return self.returncode |
121 return self.returncode |
92 |
122 |
93 def kill(self): |
123 def kill(self): |
94 os.kill(self.pid, signal.SIGKILL) |
124 os.kill(self.pid, signal.SIGKILL) |
95 |
125 |
96 if self.stdin is not None: |
126 if self.stdin is not None: |
97 self.stdin.close() |
127 self.stdin.close() |
98 self.stdin = None |
128 self.stdin = None |
|
129 |
99 if self.stdout is not None: |
130 if self.stdout is not None: |
100 self.stdout.close() |
131 self.stdout.close() |
101 self.stdout = None |
132 self.stdout = None |
|
133 |
|
134 if self.stderr is not None: |
|
135 self.stderr.close() |
|
136 self.stderr = None |
102 |
137 |
103 |
138 |
104 def call(*args): |
139 def call(*args): |
105 cmd = [] |
140 cmd = [] |
106 if isinstance(args[0], str): |
141 if isinstance(args[0], str): |