-
Notifications
You must be signed in to change notification settings - Fork 12
/
serve-stdio
executable file
·82 lines (69 loc) · 1.86 KB
/
serve-stdio
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
#!/usr/bin/env python
from __future__ import print_function
import os, sys
import signal
import nclib
argiter = iter(sys.argv)
progname = next(argiter)
daemonize = False
show_stderr = None
bind_addr = '0.0.0.0'
def usage():
print('Usage: %s [options] port command ...' % sys.argv[0])
print('Options:')
print(' -d Daemonize, run in background')
print(' -e Redirect program\'s stderr to socket')
print(' -E Hide program\'s stderr')
print(' -b addr Bind to a specific address')
sys.exit(1)
for arg in argiter:
try:
if arg == '-d':
daemonize = True
elif arg == '-e':
show_stderr = True
elif arg == '-E':
show_stderr = False
elif arg == '-b':
bind_addr = next(argiter)
else:
break
except StopIteration:
usage()
else:
usage()
try:
port = int(arg) # pylint: disable=undefined-loop-variable
except (ValueError, NameError):
usage()
def quote(s):
return "'%s'" % s.replace("'", "'\"'\"'")
command = ' '.join(map(quote, argiter))
if command == '':
usage()
if daemonize:
p = os.fork()
if p:
print(p)
sys.stdout.flush()
os._exit(0)
children = []
def reap():
i = 0
while i < len(children):
if children[i].poll() is not None:
children.pop(i)
else:
i += 1
def cleanup(*args): # pylint: disable=unused-argument
for child in children:
child.kill() # not sure how effective this is, will probably only kill the shell...
print()
sys.exit(0)
signal.signal(signal.SIGTERM, cleanup)
signal.signal(signal.SIGINT, cleanup)
for client in nclib.TCPServer((bind_addr, port)):
print('Accepted client %s:%d' % client.peer)
children.append(nclib.Process.launch(command, client, stderr=show_stderr))
client.close()
reap()