-
Notifications
You must be signed in to change notification settings - Fork 2
/
runwith.py
executable file
·99 lines (79 loc) · 2.83 KB
/
runwith.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/python
# Note that running python with the `-u` flag is required on Windows,
# in order to ensure that stdin and stdout are opened in binary, rather
# than text, mode.
import sys, json, struct, os
import subprocess
def debug(msg):
if enable_debug:
with open(debug_file, 'a') as outfile:
outfile.write(msg)
outfile.write("\n")
# Read a message from stdin and decode it.
def getMessage():
rawLength = our_stdin.read(4)
if len(rawLength) == 0:
sys.exit(0)
messageLength = struct.unpack('@I', rawLength)[0]
debug("getMessage: messageLength is %s" % messageLength)
message = our_stdin.read(messageLength).decode('utf-8')
debug("getMessage: message is %s" % message)
return json.loads(message)
# Encode a message for transmission, given its content.
def encodeMessage(messageContent):
debug("encodeMessage: messageContent is %s" % messageContent)
encodedContent = json.dumps(messageContent)
debug("encodeMessage: encodedContent is %s\n" % encodedContent)
encodedLength = struct.pack('@I', len(encodedContent))
debug("encodeMessage: encodedLength is %s" % encodedLength)
return {'length': encodedLength, 'content': encodedContent.encode()}
# Send an encoded message to stdout.
def sendMessage(encodedMessage):
debug("sendMessage: encodedMessage is %s" % encodedMessage)
debug("sendMessage: encodedMessage['length'] is %s" % encodedMessage['length'])
debug("sendMessage: encodedMessage['content'] is %s" % encodedMessage['content'])
our_stdout.write(encodedMessage['length'])
our_stdout.write(encodedMessage['content'])
our_stdout.flush()
# determine Python version
python_version = sys.version_info[0] # should be 2 or 3
if python_version == 2:
our_stdin = sys.stdin
our_stdout = sys.stdout
else:
our_stdin = sys.stdin.buffer
our_stdout = sys.stdout.buffer
# set this to true to dump things to the debug_file
enable_debug = False
debug_file = "/tmp/runwith_debug.log"
receivedMessage = getMessage()
debug("main: receivedMessage is %s" % receivedMessage)
cmd = receivedMessage['cmd']
shell = receivedMessage['shell']
wait = receivedMessage['wait']
use_shell = False
command = cmd
if shell:
use_shell = True
command = ' '.join(cmd)
devnull = open(os.devnull, 'w')
child_stdout = devnull
child_stderr = devnull
close_fds = True
if wait:
child_stdout = subprocess.PIPE
child_stderr = subprocess.PIPE
close_fds = False
proc = subprocess.Popen(command, stdout = child_stdout, stderr = child_stderr, shell = use_shell, close_fds = close_fds)
msg = { 'pid': proc.pid, 'shell': use_shell, 'wait': wait }
if wait:
stdout, stderr = proc.communicate()
exit_code = proc.returncode
msg['exit-status'] = exit_code
msg['stderr'] = stderr.decode()
msg['stdout'] = stdout.decode()
else:
msg['exit-status'] = 'N/A'
msg['stderr'] = 'N/A'
msg['stdout'] = 'N/A'
sendMessage(encodeMessage(msg))