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

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: drtomc
  • Date: 2007-12-11 03:26:29 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:25
A bit more work on the userdb stuff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
# usage:
4
 
#   python-console <port> <magic> [<working-dir>]
5
 
 
6
 
import cjson
7
 
import codeop
8
 
import md5
9
 
import os
10
 
import Queue
11
 
import signal
12
 
import socket
13
 
import sys
14
 
from threading import Thread
15
 
from functools import partial
16
 
 
17
 
import common.chat
18
 
 
19
 
class Interrupt(Exception):
20
 
    def __init__(self):
21
 
        Exception.__init__(self, "Interrupted!")
22
 
 
23
 
class ExpiryTimer(object):
24
 
    def __init__(self, idle):
25
 
        self.idle = idle
26
 
        signal.signal(signal.SIGALRM, partial(self.timeout))
27
 
 
28
 
    def ping(self):
29
 
        signal.alarm(self.idle)
30
 
 
31
 
    def start(self, time):
32
 
        signal.alarm(time)
33
 
 
34
 
    def stop(self):
35
 
        self.ping()
36
 
 
37
 
    def timeout(self, signum, frame):
38
 
        sys.exit(1)
39
 
        
40
 
class StdinFromWeb(object):
41
 
    def __init__(self, cmdQ, lineQ):
42
 
        self.cmdQ = cmdQ
43
 
        self.lineQ = lineQ
44
 
 
45
 
    def readline(self):
46
 
        self.cmdQ.put({"input":None})
47
 
        expiry.ping()
48
 
        ln = self.lineQ.get()
49
 
        if 'chat' in ln:
50
 
            return ln['chat']
51
 
        if 'interrupt' in ln:
52
 
            raise Interrupt()
53
 
 
54
 
class StdoutToWeb(object):
55
 
    def __init__(self, cmdQ, lineQ):
56
 
        self.cmdQ = cmdQ
57
 
        self.lineQ = lineQ
58
 
        self.remainder = ''
59
 
 
60
 
    def write(self, stuff):
61
 
        self.remainder = self.remainder + stuff
62
 
 
63
 
        # if there's less than 128 bytes, buffer
64
 
        if len(self.remainder) < 128:
65
 
            return
66
 
 
67
 
        # if there's lots, then send it in 1/2K blocks
68
 
        while len(self.remainder) > 512:
69
 
            blk = self.remainder[0:512]
70
 
            self.cmdQ.put({"output":blk})
71
 
            expiry.ping()
72
 
            ln = self.lineQ.get()
73
 
            self.remainder = self.remainder[512:]
74
 
 
75
 
        # Finally, split the remainder up into lines, and ship all the
76
 
        # completed lines off to the server.
77
 
        lines = self.remainder.split("\n")
78
 
        self.remainder = lines[-1]
79
 
        del lines[-1]
80
 
 
81
 
        if len(lines) > 0:
82
 
            lines.append('')
83
 
            text = "\n".join(lines)
84
 
            self.cmdQ.put({"output":text})
85
 
            expiry.ping()
86
 
            ln = self.lineQ.get()
87
 
            if 'interrupt' in ln:
88
 
                raise Interrupt()
89
 
 
90
 
    def flush(self):
91
 
        if len(self.remainder) > 0:
92
 
            self.cmdQ.put({"output":self.remainder})
93
 
            expiry.ping()
94
 
            ln = self.lineQ.get()
95
 
            self.remainder = ''
96
 
            if 'interrupt' in ln:
97
 
                raise Interrupt()
98
 
 
99
 
class PythonRunner(Thread):
100
 
    def __init__(self, cmdQ, lineQ):
101
 
        self.cmdQ = cmdQ
102
 
        self.lineQ = lineQ
103
 
        self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
104
 
        Thread.__init__(self)
105
 
 
106
 
    def execCmd(self, cmd):
107
 
        try:
108
 
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
109
 
            sys.stdout = self.stdout
110
 
            sys.stderr = self.stdout
111
 
            res = eval(cmd, self.globs)
112
 
            self.stdout.flush()
113
 
            self.cmdQ.put({"okay":res})
114
 
            self.curr_cmd = ''
115
 
        except Exception, exc:
116
 
            self.stdout.flush()
117
 
            self.cmdQ.put({"exc":str(exc)})
118
 
            self.curr_cmd = ''
119
 
 
120
 
    def run(self):
121
 
        self.globs = {}
122
 
        self.globs['__builtins__'] = globals()['__builtins__']
123
 
        self.curr_cmd = ''
124
 
        compiler = codeop.CommandCompiler()
125
 
 
126
 
        while True:
127
 
            ln = self.lineQ.get()
128
 
            if 'chat' in ln:
129
 
                if self.curr_cmd == '':
130
 
                    self.curr_cmd = ln['chat']
131
 
                else:
132
 
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
133
 
                try:
134
 
                    cmd = compiler(self.curr_cmd)
135
 
                    if cmd is None:
136
 
                        # The command was incomplete,
137
 
                        # so send back a None, so the
138
 
                        # client can print a '...'
139
 
                        self.cmdQ.put({"more":None})
140
 
                    else:
141
 
                        self.execCmd(cmd)
142
 
                except Exception, exc:
143
 
                    self.stdout.flush()
144
 
                    self.cmdQ.put({"exc":str(exc)})
145
 
                    self.curr_cmd = ''
146
 
            if 'block' in ln:
147
 
                # throw away a partial command.
148
 
                try:
149
 
                    cmd = compile(ln['block'], "<web session>", 'exec');
150
 
                    self.execCmd(cmd)
151
 
                except Exception, exc:
152
 
                    self.stdout.flush()
153
 
                    self.cmdQ.put({"exc":str(exc)})
154
 
                    self.curr_cmd = ''
155
 
 
156
 
def daemonize():
157
 
    if os.fork():   # launch child and...
158
 
        os._exit(0) # kill off parent
159
 
    os.setsid()
160
 
    if os.fork():   # launch child and...
161
 
        os._exit(0) # kill off parent again.
162
 
    os.umask(077)
163
 
 
164
 
# The global 'magic' is the secret that the client and server share
165
 
# which is used to create and md5 digest to authenticate requests.
166
 
# It is assigned a real value at startup.
167
 
magic = ''
168
 
 
169
 
cmdQ = Queue.Queue()
170
 
lineQ = Queue.Queue()
171
 
interpThread = PythonRunner(cmdQ, lineQ)
172
 
 
173
 
# Default expiry time of 15 minutes
174
 
expiry = ExpiryTimer(15 * 60)
175
 
 
176
 
def initializer():
177
 
    interpThread.setDaemon(True)
178
 
    interpThread.start()
179
 
    expiry.ping()
180
 
 
181
 
def dispatch_msg(msg):
182
 
    expiry.ping()
183
 
    lineQ.put({msg['cmd']:msg['text']})
184
 
    return cmdQ.get()
185
 
 
186
 
if __name__ == "__main__":
187
 
    port = int(sys.argv[1])
188
 
    magic = sys.argv[2]
189
 
    if len(sys.argv) >= 4:
190
 
        # working_dir
191
 
        os.chdir(sys.argv[3])
192
 
        os.environ['HOME'] = sys.argv[3]
193
 
 
194
 
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)