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

418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
1
#!/usr/bin/python
2
3
# usage:
603 by mattgiuca
Console now starts up in the user's home directory.
4
#   python-console <port> <magic> [<working-dir>]
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
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
526 by drtomc
python-console: trivial bugfix - missing import.
15
from functools import partial
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
16
432 by drtomc
usrmgt: more work on this. Still some work to go.
17
import common.chat
18
598 by drtomc
console: send output back to the browser progressively.
19
class Interrupt(Exception):
20
    pass
21
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
22
class ExpiryTimer(object):
23
    def __init__(self, idle):
24
        self.idle = idle
564 by drtomc
python-console: Fix the timeout code.
25
        signal.signal(signal.SIGALRM, partial(self.timeout))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
26
27
    def ping(self):
28
        signal.alarm(self.idle)
29
30
    def start(self, time):
31
        signal.alarm(time)
32
33
    def stop(self):
34
        self.ping()
35
36
    def timeout(self, signum, frame):
37
        sys.exit(1)
38
        
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
39
class StdinFromWeb(object):
40
    def __init__(self, cmdQ, lineQ):
41
        self.cmdQ = cmdQ
42
        self.lineQ = lineQ
43
44
    def readline(self):
45
        self.cmdQ.put({"input":None})
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
46
        expiry.ping()
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
47
        ln = self.lineQ.get()
48
        if 'chat' in ln:
49
            return ln['chat']
50
598 by drtomc
console: send output back to the browser progressively.
51
class StdoutToWeb(object):
52
    def __init__(self, cmdQ, lineQ):
53
        self.cmdQ = cmdQ
54
        self.lineQ = lineQ
55
        self.remainder = ''
56
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]
63
        del lines[-1]
64
65
        if len(lines) > 0:
599 by drtomc
console: improve end of line handling.
66
            lines.append('')
67
            text = "\n".join(lines)
68
            self.cmdQ.put({"output":text})
598 by drtomc
console: send output back to the browser progressively.
69
            expiry.ping()
70
            ln = self.lineQ.get()
71
            if 'interrupt' in ln:
72
                raise Interrupt()
73
74
    def flush(self):
599 by drtomc
console: improve end of line handling.
75
        if len(self.remainder) > 0:
76
            self.cmdQ.put({"output":self.remainder})
77
            expiry.ping()
78
            ln = self.lineQ.get()
79
            self.remainder = ''
80
            if 'interrupt' in ln:
81
                raise Interrupt()
598 by drtomc
console: send output back to the browser progressively.
82
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
83
class PythonRunner(Thread):
84
    def __init__(self, cmdQ, lineQ):
85
        self.cmdQ = cmdQ
86
        self.lineQ = lineQ
599 by drtomc
console: improve end of line handling.
87
        self.stdout = None
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
88
        Thread.__init__(self)
89
90
    def execCmd(self, cmd):
91
        try:
92
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
599 by drtomc
console: improve end of line handling.
93
            self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
94
            sys.stdout = self.stdout
95
            sys.stderr = self.stdout
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
96
            res = eval(cmd, self.globs, self.locls)
599 by drtomc
console: improve end of line handling.
97
            self.stdout.flush()
98
            self.cmdQ.put({"okay":res})
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
99
            self.curr_cmd = ''
100
        except Exception, exc:
599 by drtomc
console: improve end of line handling.
101
            self.stdout.flush()
102
            self.cmdQ.put({"exc":str(exc)})
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
103
            self.curr_cmd = ''
104
105
    def run(self):
598 by drtomc
console: send output back to the browser progressively.
106
        self.globs = {}
107
        self.globs['__builtins__'] = globals()['__builtins__']
108
        self.locls = {}
109
        self.curr_cmd = ''
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
110
        compiler = codeop.CommandCompiler()
111
112
        while True:
113
            ln = self.lineQ.get()
114
            if 'chat' in ln:
115
                if self.curr_cmd == '':
116
                    self.curr_cmd = ln['chat']
117
                else:
118
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
119
                try:
120
                    cmd = compiler(self.curr_cmd)
121
                    if cmd is None:
122
                        # The command was incomplete,
123
                        # so send back a None, so the
124
                        # client can print a '...'
125
                        self.cmdQ.put({"more":None})
126
                    else:
127
                        self.execCmd(cmd)
128
                except Exception, exc:
599 by drtomc
console: improve end of line handling.
129
                    self.stdout.flush()
130
                    self.cmdQ.put({"exc":str(exc)})
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
131
                    self.curr_cmd = ''
132
            if 'block' in ln:
133
                # throw away a partial command.
134
                try:
135
                    cmd = compile(ln['block'], "<web session>", 'exec');
136
                    self.execCmd(cmd)
137
                except Exception, exc:
599 by drtomc
console: improve end of line handling.
138
                    self.stdout.flush()
139
                    self.cmdQ.put({"exc":str(exc)})
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
140
                    self.curr_cmd = ''
141
142
def daemonize():
143
    if os.fork():   # launch child and...
144
        os._exit(0) # kill off parent
145
    os.setsid()
146
    if os.fork():   # launch child and...
147
        os._exit(0) # kill off parent again.
148
    os.umask(077)
149
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.
153
magic = ''
154
155
cmdQ = Queue.Queue()
156
lineQ = Queue.Queue()
157
interpThread = PythonRunner(cmdQ, lineQ)
158
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
159
# Default expiry time of 15 minutes
160
expiry = ExpiryTimer(15 * 60)
161
432 by drtomc
usrmgt: more work on this. Still some work to go.
162
def initializer():
163
    interpThread.setDaemon(True)
164
    interpThread.start()
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
165
    expiry.ping()
432 by drtomc
usrmgt: more work on this. Still some work to go.
166
167
def dispatch_msg(msg):
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
168
    expiry.ping()
432 by drtomc
usrmgt: more work on this. Still some work to go.
169
    lineQ.put({msg['cmd']:msg['text']})
170
    return cmdQ.get()
171
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
172
if __name__ == "__main__":
173
    port = int(sys.argv[1])
174
    magic = sys.argv[2]
603 by mattgiuca
Console now starts up in the user's home directory.
175
    if len(sys.argv) >= 4:
176
        # working_dir
177
        os.chdir(sys.argv[3])
418 by mattgiuca
Renamed trunk/console to trunk/scripts. We are now able to put more scripts in
178
432 by drtomc
usrmgt: more work on this. Still some work to go.
179
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)