~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to console/python-console

  • Committer: mattgiuca
  • Date: 2008-02-05 01:41:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:409
Moved www/conf and www/common to a new directory lib. This separates the "web"
part of IVLE from what is becoming less web oriented (at least from Apache's
standpoint).
Modified setup.py to install this lib directory correctly and write conf in
the right place. Also adds the lib directory to ivle.pth.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# usage:
 
4
#   python-console <port> <magic>
 
5
 
 
6
import cjson
 
7
import codeop
 
8
import cStringIO
 
9
import md5
 
10
import os
 
11
import Queue
 
12
import signal
 
13
import socket
 
14
import sys
 
15
from threading import Thread
 
16
 
 
17
class StdinFromWeb(object):
 
18
    def __init__(self, cmdQ, lineQ):
 
19
        self.cmdQ = cmdQ
 
20
        self.lineQ = lineQ
 
21
 
 
22
    def readline(self):
 
23
        # stop the clock!
 
24
        signal.alarm(0)
 
25
        self.cmdQ.put({"input":None})
 
26
        ln = self.lineQ.get()
 
27
        if 'chat' in ln:
 
28
            # restart the clock:
 
29
            # Some of our 5 seconds may have elapsed, but never mind.
 
30
            signal.alarm(5)
 
31
            return ln['chat']
 
32
 
 
33
class PythonRunner(Thread):
 
34
    def __init__(self, cmdQ, lineQ):
 
35
        self.cmdQ = cmdQ
 
36
        self.lineQ = lineQ
 
37
        self.out = cStringIO.StringIO()
 
38
        Thread.__init__(self)
 
39
 
 
40
    def execCmd(self, cmd):
 
41
        try:
 
42
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
 
43
            sys.stdout = self.out
 
44
            sys.stderr = self.out
 
45
            signal.alarm(5)
 
46
            res = eval(cmd, self.globs, self.locls)
 
47
            signal.alarm(0)
 
48
            self.cmdQ.put({"okay":(self.out.getvalue(),res)})
 
49
            self.curr_cmd = ''
 
50
            self.out = cStringIO.StringIO()
 
51
        except Exception, exc:
 
52
            signal.alarm(0)
 
53
            self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
 
54
            self.curr_cmd = ''
 
55
            self.out = cStringIO.StringIO()
 
56
 
 
57
    def run(self):
 
58
        self.init_state()
 
59
        compiler = codeop.CommandCompiler()
 
60
 
 
61
        while True:
 
62
            ln = self.lineQ.get()
 
63
            if 'chat' in ln:
 
64
                if self.curr_cmd == '':
 
65
                    self.curr_cmd = ln['chat']
 
66
                else:
 
67
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
 
68
                try:
 
69
                    cmd = compiler(self.curr_cmd)
 
70
                    if cmd is None:
 
71
                        # The command was incomplete,
 
72
                        # so send back a None, so the
 
73
                        # client can print a '...'
 
74
                        self.cmdQ.put({"more":None})
 
75
                    else:
 
76
                        self.execCmd(cmd)
 
77
                except Exception, exc:
 
78
                    signal.alarm(0)
 
79
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
 
80
                    self.curr_cmd = ''
 
81
                    self.out = cStringIO.StringIO()
 
82
            if 'block' in ln:
 
83
                # throw away a partial command.
 
84
                try:
 
85
                    cmd = compile(ln['block'], "<web session>", 'exec');
 
86
                    self.execCmd(cmd)
 
87
                except Exception, exc:
 
88
                    signal.alarm(0)
 
89
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
 
90
                    self.curr_cmd = ''
 
91
                    self.out = cStringIO.StringIO()
 
92
 
 
93
    def init_state(self):
 
94
        self.globs = {}
 
95
        self.globs['__builtins__'] = globals()['__builtins__']
 
96
        self.locls = {}
 
97
        self.curr_cmd = ''
 
98
 
 
99
def daemonize():
 
100
    if os.fork():   # launch child and...
 
101
        os._exit(0) # kill off parent
 
102
    os.setsid()
 
103
    if os.fork():   # launch child and...
 
104
        os._exit(0) # kill off parent again.
 
105
    os.umask(077)
 
106
 
 
107
# The global 'magic' is the secret that the client and server share
 
108
# which is used to create and md5 digest to authenticate requests.
 
109
# It is assigned a real value at startup.
 
110
magic = ''
 
111
 
 
112
cmdQ = Queue.Queue()
 
113
lineQ = Queue.Queue()
 
114
interpThread = PythonRunner(cmdQ, lineQ)
 
115
 
 
116
if __name__ == "__main__":
 
117
    port = int(sys.argv[1])
 
118
    magic = sys.argv[2]
 
119
 
 
120
    # Attempt to open the socket.
 
121
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
122
    s.bind(('', port))
 
123
    s.listen(1)
 
124
 
 
125
    # Excellent! It worked. Let's turn ourself into a daemon,
 
126
    # then get on with the job of being a python interpreter.
 
127
    daemonize()
 
128
 
 
129
    interpThread.setDaemon(True)
 
130
    interpThread.start()
 
131
 
 
132
    while True:
 
133
        (conn, addr) = s.accept()
 
134
        try:
 
135
            # Grab the input
 
136
            buf = cStringIO.StringIO()
 
137
            blk = conn.recv(1024)
 
138
            while blk:
 
139
                buf.write(blk)
 
140
                try:
 
141
                    blk = conn.recv(1024, socket.MSG_DONTWAIT)
 
142
                except:
 
143
                    # Exception thrown if it WOULD block (but we
 
144
                    # told it not to wait) - ie. we are done
 
145
                    blk = None
 
146
            inp = buf.getvalue()
 
147
            msg = cjson.decode(inp)
 
148
            
 
149
            # Check that the message is 
 
150
            digest = md5.new(msg['text'] + magic).digest().encode('hex')
 
151
            if msg['digest'] != digest:
 
152
                conn.close()
 
153
                continue
 
154
 
 
155
            lineQ.put({msg['cmd']:msg['text']})
 
156
            r = cmdQ.get()
 
157
            conn.sendall(cjson.encode(r))
 
158
            conn.close()
 
159
        except Exception, e:
 
160
            conn.close()