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