~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
 
 
52
 
class StdoutToWeb(object):
53
 
    def __init__(self, cmdQ, lineQ):
54
 
        self.cmdQ = cmdQ
55
 
        self.lineQ = lineQ
56
 
        self.remainder = ''
57
 
 
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
62
 
            return
63
 
 
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]
69
 
        del lines[-1]
70
 
 
71
 
        if len(lines) > 0:
72
 
            lines.append('')
73
 
            text = "\n".join(lines)
74
 
            self.cmdQ.put({"output":text})
75
 
            expiry.ping()
76
 
            ln = self.lineQ.get()
77
 
            if 'interrupt' in ln:
78
 
                raise Interrupt()
79
 
 
80
 
    def flush(self):
81
 
        if len(self.remainder) > 0:
82
 
            self.cmdQ.put({"output":self.remainder})
83
 
            expiry.ping()
84
 
            ln = self.lineQ.get()
85
 
            self.remainder = ''
86
 
            if 'interrupt' in ln:
87
 
                raise Interrupt()
88
 
 
89
 
class PythonRunner(Thread):
90
 
    def __init__(self, cmdQ, lineQ):
91
 
        self.cmdQ = cmdQ
92
 
        self.lineQ = lineQ
93
 
        self.stdout = None
94
 
        Thread.__init__(self)
95
 
 
96
 
    def execCmd(self, cmd):
97
 
        try:
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)
103
 
            self.stdout.flush()
104
 
            self.cmdQ.put({"okay":res})
105
 
            self.curr_cmd = ''
106
 
        except Exception, exc:
107
 
            self.stdout.flush()
108
 
            self.cmdQ.put({"exc":str(exc)})
109
 
            self.curr_cmd = ''
110
 
 
111
 
    def run(self):
112
 
        self.globs = {}
113
 
        self.globs['__builtins__'] = globals()['__builtins__']
114
 
        self.locls = {}
115
 
        self.curr_cmd = ''
116
 
        compiler = codeop.CommandCompiler()
117
 
 
118
 
        while True:
119
 
            ln = self.lineQ.get()
120
 
            if 'chat' in ln:
121
 
                if self.curr_cmd == '':
122
 
                    self.curr_cmd = ln['chat']
123
 
                else:
124
 
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
125
 
                try:
126
 
                    cmd = compiler(self.curr_cmd)
127
 
                    if cmd is None:
128
 
                        # The command was incomplete,
129
 
                        # so send back a None, so the
130
 
                        # client can print a '...'
131
 
                        self.cmdQ.put({"more":None})
132
 
                    else:
133
 
                        self.execCmd(cmd)
134
 
                except Exception, exc:
135
 
                    self.stdout.flush()
136
 
                    self.cmdQ.put({"exc":str(exc)})
137
 
                    self.curr_cmd = ''
138
 
            if 'block' in ln:
139
 
                # throw away a partial command.
140
 
                try:
141
 
                    cmd = compile(ln['block'], "<web session>", 'exec');
142
 
                    self.execCmd(cmd)
143
 
                except Exception, exc:
144
 
                    self.stdout.flush()
145
 
                    self.cmdQ.put({"exc":str(exc)})
146
 
                    self.curr_cmd = ''
147
 
 
148
 
def daemonize():
149
 
    if os.fork():   # launch child and...
150
 
        os._exit(0) # kill off parent
151
 
    os.setsid()
152
 
    if os.fork():   # launch child and...
153
 
        os._exit(0) # kill off parent again.
154
 
    os.umask(077)
155
 
 
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.
159
 
magic = ''
160
 
 
161
 
cmdQ = Queue.Queue()
162
 
lineQ = Queue.Queue()
163
 
interpThread = PythonRunner(cmdQ, lineQ)
164
 
 
165
 
# Default expiry time of 15 minutes
166
 
expiry = ExpiryTimer(15 * 60)
167
 
 
168
 
def initializer():
169
 
    interpThread.setDaemon(True)
170
 
    interpThread.start()
171
 
    expiry.ping()
172
 
 
173
 
def dispatch_msg(msg):
174
 
    expiry.ping()
175
 
    lineQ.put({msg['cmd']:msg['text']})
176
 
    return cmdQ.get()
177
 
 
178
 
if __name__ == "__main__":
179
 
    port = int(sys.argv[1])
180
 
    magic = sys.argv[2]
181
 
    if len(sys.argv) >= 4:
182
 
        # working_dir
183
 
        os.chdir(sys.argv[3])
184
 
 
185
 
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)