4
# python-console <port> <magic> [<working-dir>]
14
from threading import Thread
15
from functools import partial
19
class Interrupt(Exception):
21
Exception.__init__(self, "Interrupted!")
23
class ExpiryTimer(object):
24
def __init__(self, idle):
26
signal.signal(signal.SIGALRM, partial(self.timeout))
29
signal.alarm(self.idle)
31
def start(self, time):
37
def timeout(self, signum, frame):
40
class StdinFromWeb(object):
41
def __init__(self, cmdQ, lineQ):
46
self.cmdQ.put({"input":None})
52
class StdoutToWeb(object):
53
def __init__(self, cmdQ, lineQ):
58
def write(self, stuff):
59
# if there's less than 1K, buffer
60
if len(self.remainder) + len(stuff) < 128:
61
self.remainder = self.remainder + stuff
64
# Split the content up into lines, and ship all the completed
65
# lines off to the server.
66
lines = stuff.split("\n")
67
lines[0] = self.remainder + lines[0]
68
self.remainder = lines[-1]
73
text = "\n".join(lines)
74
self.cmdQ.put({"output":text})
81
if len(self.remainder) > 0:
82
self.cmdQ.put({"output":self.remainder})
89
class PythonRunner(Thread):
90
def __init__(self, cmdQ, lineQ):
96
def execCmd(self, cmd):
98
sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
99
self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
100
sys.stdout = self.stdout
101
sys.stderr = self.stdout
102
res = eval(cmd, self.globs, self.locls)
104
self.cmdQ.put({"okay":res})
106
except Exception, exc:
108
self.cmdQ.put({"exc":str(exc)})
113
self.globs['__builtins__'] = globals()['__builtins__']
116
compiler = codeop.CommandCompiler()
119
ln = self.lineQ.get()
121
if self.curr_cmd == '':
122
self.curr_cmd = ln['chat']
124
self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
126
cmd = compiler(self.curr_cmd)
128
# The command was incomplete,
129
# so send back a None, so the
130
# client can print a '...'
131
self.cmdQ.put({"more":None})
134
except Exception, exc:
136
self.cmdQ.put({"exc":str(exc)})
139
# throw away a partial command.
141
cmd = compile(ln['block'], "<web session>", 'exec');
143
except Exception, exc:
145
self.cmdQ.put({"exc":str(exc)})
149
if os.fork(): # launch child and...
150
os._exit(0) # kill off parent
152
if os.fork(): # launch child and...
153
os._exit(0) # kill off parent again.
156
# The global 'magic' is the secret that the client and server share
157
# which is used to create and md5 digest to authenticate requests.
158
# It is assigned a real value at startup.
162
lineQ = Queue.Queue()
163
interpThread = PythonRunner(cmdQ, lineQ)
165
# Default expiry time of 15 minutes
166
expiry = ExpiryTimer(15 * 60)
169
interpThread.setDaemon(True)
173
def dispatch_msg(msg):
175
lineQ.put({msg['cmd']:msg['text']})
178
if __name__ == "__main__":
179
port = int(sys.argv[1])
181
if len(sys.argv) >= 4:
183
os.chdir(sys.argv[3])
185
common.chat.start_server(port, magic, True, dispatch_msg, initializer)