4
# python-console <port> <magic> [<working-dir>]
14
from threading import Thread
15
from functools import partial
19
class Interrupt(Exception):
22
class ExpiryTimer(object):
23
def __init__(self, idle):
25
signal.signal(signal.SIGALRM, partial(self.timeout))
28
signal.alarm(self.idle)
30
def start(self, time):
36
def timeout(self, signum, frame):
39
class StdinFromWeb(object):
40
def __init__(self, cmdQ, lineQ):
45
self.cmdQ.put({"input":None})
51
class StdoutToWeb(object):
52
def __init__(self, cmdQ, lineQ):
57
def write(self, stuff):
58
# Split the content up into lines, and ship all the completed
59
# lines off to the server.
60
lines = stuff.split("\n")
61
lines[0] = self.remainder + lines[0]
62
self.remainder = lines[-1]
67
text = "\n".join(lines)
68
self.cmdQ.put({"output":text})
75
if len(self.remainder) > 0:
76
self.cmdQ.put({"output":self.remainder})
83
class PythonRunner(Thread):
84
def __init__(self, cmdQ, lineQ):
90
def execCmd(self, cmd):
92
sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
93
self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
94
sys.stdout = self.stdout
95
sys.stderr = self.stdout
96
res = eval(cmd, self.globs, self.locls)
98
self.cmdQ.put({"okay":res})
100
except Exception, exc:
102
self.cmdQ.put({"exc":str(exc)})
107
self.globs['__builtins__'] = globals()['__builtins__']
110
compiler = codeop.CommandCompiler()
113
ln = self.lineQ.get()
115
if self.curr_cmd == '':
116
self.curr_cmd = ln['chat']
118
self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
120
cmd = compiler(self.curr_cmd)
122
# The command was incomplete,
123
# so send back a None, so the
124
# client can print a '...'
125
self.cmdQ.put({"more":None})
128
except Exception, exc:
130
self.cmdQ.put({"exc":str(exc)})
133
# throw away a partial command.
135
cmd = compile(ln['block'], "<web session>", 'exec');
137
except Exception, exc:
139
self.cmdQ.put({"exc":str(exc)})
143
if os.fork(): # launch child and...
144
os._exit(0) # kill off parent
146
if os.fork(): # launch child and...
147
os._exit(0) # kill off parent again.
150
# The global 'magic' is the secret that the client and server share
151
# which is used to create and md5 digest to authenticate requests.
152
# It is assigned a real value at startup.
156
lineQ = Queue.Queue()
157
interpThread = PythonRunner(cmdQ, lineQ)
159
# Default expiry time of 15 minutes
160
expiry = ExpiryTimer(15 * 60)
163
interpThread.setDaemon(True)
167
def dispatch_msg(msg):
169
lineQ.put({msg['cmd']:msg['text']})
172
if __name__ == "__main__":
173
port = int(sys.argv[1])
175
if len(sys.argv) >= 4:
177
os.chdir(sys.argv[3])
179
common.chat.start_server(port, magic, True, dispatch_msg, initializer)