-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfcli_server_lib.py
136 lines (102 loc) · 3.02 KB
/
fcli_server_lib.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/python
"""
fcli_server_lib.py
"""
from __future__ import print_function
import getopt
import os
import sys
from util import log, netstring_readfd, netstring_encode
def ParseRequest(fcli_req_args):
opts, args = getopt.getopt(fcli_req_args, "d:r:w:i:o:e:")
fds = []
# TODO:
# -k or -s or -h to stop/halt the process?
# -s for stats?
for name, value in opts:
log('flag %s = %s', name, value)
if name == '-d':
#log('chdir %s', value)
os.chdir(value) # TODO: error handling
elif name == '-r':
# The -r must come BEFORE -i -o -e
# BLOCKS unless someone opened for writing.
fd = os.open(value, os.O_RDONLY)
fds.append(fd)
elif name == '-w':
# The -w must come BEFORE -i -o -e
fd = os.open(value, os.O_WRONLY)
fds.append(fd)
elif name == '-i': # redir stdin
log('stdin %r', value)
index = int(value)
# TODO: IndexError is protocol error
fd = fds[index]
os.dup2(fd, 0)
os.close(fd)
log('dup stdin %d done', fd)
elif name == '-o': # redir stdout
log('stdout %r', value)
index = int(value)
fd = fds[index]
os.dup2(fd, 1)
os.close(fd)
log('dup stdout %d done', fd)
elif name == '-e': # redir stderr
log('stderr %r', value)
index = int(value)
fd = fds[index]
os.dup2(fd, 2)
os.close(fd)
log('dup stderr %d done', fd)
else:
raise AssertionError() # shouldn't get here
log('ParseRequest done')
# close stdout and stderr afterward?
to_close = [1, 2]
return args, to_close
def _MainLoop(main_func, in_f, out_f):
while True:
log('MainLoop top')
try:
request = netstring_readfd(in_f)
except EOFError:
break
# remove last one since NUL-terminated
fcli_req_args = request.split('\0')[:-1]
log('MainLoop got request %r', fcli_req_args)
try:
argv, to_close = ParseRequest(fcli_req_args)
except getopt.GetoptError as err:
# TODO: Write -e protocol error
raise RuntimeError(str(err))
log('argv = %r', argv)
try:
status = main_func(argv)
except Exception as e:
# TODO: catch it and return status=1?
raise
for fd in to_close:
log('worker closing fd %d', fd)
os.close(fd)
# -s for status, for symmetry
# Other info could be put here? Like the number of requests server or
# something?
response = ['-s', status]
response_str = ''.join('%s\0' % s for s in response)
t = netstring_encode(response_str)
log('writing back %r', t)
os.write(out_f, t)
return 0
def MainLoop(main_func):
# TODO: Remove this as an env variable so we don't confuse other processes.
# Also remove FCLI_VERSION.
fcli_in = os.getenv('FCLI_IN')
fcli_out = os.getenv('FCLI_OUT')
in_f = os.open(fcli_in, os.O_RDWR)
out_f = os.open(fcli_out, os.O_RDWR)
_MainLoop(main_func, in_f, out_f)
# NOTE: It doesn't return? We just kill it? Or we can process the '-k'
# command. To shutdown.
os.close(in_f)
os.close(out_f)