/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
1
#!/usr/bin/python
2
# -*- mode: python; coding: utf-8 -*-
3
4
from __future__ import division, absolute_import, with_statement
5
6
import sys
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
7
import os
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
8
import signal
9
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
10
import datetime
11
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
12
import urwid.curses_display
13
import urwid
14
15
from dbus.mainloop.glib import DBusGMainLoop
16
import gobject
17
18
import dbus
19
20
import UserList
21
22
# Some useful constants
23
domain = 'se.bsnet.fukt'
24
server_interface = domain + '.Mandos'
25
client_interface = domain + '.Mandos.Client'
26
version = "1.0.14"
27
28
# Always run in monochrome mode
29
urwid.curses_display.curses.has_colors = lambda : False
30
31
# Urwid doesn't support blinking, but we want it.  Since we have no
32
# use for underline on its own, we make underline also always blink.
33
urwid.curses_display.curses.A_UNDERLINE |= (
34
    urwid.curses_display.curses.A_BLINK)
35
36
class MandosClientPropertyCache(object):
37
    """This wraps a Mandos Client D-Bus proxy object, caches the
38
    properties and calls a hook function when any of them are
39
    changed.
40
    """
41
    def __init__(self, proxy_object=None, properties=None, *args,
42
                 **kwargs):
43
        self.proxy = proxy_object # Mandos Client proxy object
44
        
45
        if properties is None:
46
            self.properties = dict()
47
        else:
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
48
            self.properties = properties
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
49
        self.proxy.connect_to_signal(u"PropertyChanged",
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
50
                                     self.property_changed,
51
                                     client_interface,
52
                                     byte_arrays=True)
53
        
54
        if properties is None:
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
55
            self.properties.update(self.proxy.GetAll(client_interface,
56
                                                     dbus_interface =
57
                                                     dbus.PROPERTIES_IFACE))
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
58
        super(MandosClientPropertyCache, self).__init__(
59
            proxy_object=proxy_object,
60
            properties=properties, *args, **kwargs)
61
    
62
    def property_changed(self, property=None, value=None):
63
        """This is called whenever we get a PropertyChanged signal
64
        It updates the changed property in the "properties" dict.
65
        """
66
        # Update properties dict with new value
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
67
        self.properties[property] = value
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
68
69
70
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
71
    """A Mandos Client which is visible on the screen.
72
    """
73
    
74
    def __init__(self, server_proxy_object=None, update_hook=None,
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
75
                 delete_hook=None, logger=None, *args, **kwargs):
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
76
        # Called on update
77
        self.update_hook = update_hook
78
        # Called on delete
79
        self.delete_hook = delete_hook
80
        # Mandos Server proxy object
81
        self.server_proxy_object = server_proxy_object
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
82
        # Logger
83
        self.logger = logger
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
84
        
85
        # The widget shown normally
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
86
        self._text_widget = urwid.Text(u"")
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
87
        # The widget shown when we have focus
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
88
        self._focus_text_widget = urwid.Text(u"")
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
89
        super(MandosClientWidget, self).__init__(
90
            update_hook=update_hook, delete_hook=delete_hook,
91
            *args, **kwargs)
92
        self.update()
93
        self.opened = False
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
94
        self.proxy.connect_to_signal(u"CheckerCompleted",
95
                                     self.checker_completed,
96
                                     client_interface,
97
                                     byte_arrays=True)
98
        self.proxy.connect_to_signal(u"CheckerStarted",
99
                                     self.checker_started,
100
                                     client_interface,
101
                                     byte_arrays=True)
102
        self.proxy.connect_to_signal(u"GotSecret",
103
                                     self.got_secret,
104
                                     client_interface,
105
                                     byte_arrays=True)
106
        self.proxy.connect_to_signal(u"Rejected",
107
                                     self.rejected,
108
                                     client_interface,
109
                                     byte_arrays=True)
110
    
111
    def checker_completed(self, exitstatus, condition, command):
112
        if exitstatus == 0:
113
            self.logger(u'Checker for client %s (command "%s")'
114
                        u' was successful'
115
                        % (self.properties[u"name"], command))
116
            return
117
        if os.WIFEXITED(condition):
118
            self.logger(u'Checker for client %s (command "%s")'
119
                        u' failed with exit code %s'
120
                        % (self.properties[u"name"], command,
121
                           os.WEXITSTATUS(condition)))
122
            return
123
        if os.WIFSIGNALED(condition):
124
            self.logger(u'Checker for client %s (command "%s")'
125
                        u' was killed by signal %s'
126
                        % (self.properties[u"name"], command,
127
                           os.WTERMSIG(condition)))
128
            return
129
        if os.WCOREDUMP(condition):
130
            self.logger(u'Checker for client %s (command "%s")'
131
                        u' dumped core'
132
                        % (self.properties[u"name"], command))
133
        self.logger(u'Checker for client %s completed mysteriously')
134
    
135
    def checker_started(self, command):
136
        self.logger(u'Client %s started checker "%s"'
137
                    % (self.properties[u"name"], unicode(command)))
138
    
139
    def got_secret(self):
140
        self.logger(u'Client %s received its secret'
141
                    % self.properties[u"name"])
142
    
143
    def rejected(self):
144
        self.logger(u'Client %s was rejected'
145
                    % self.properties[u"name"])
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
146
    
147
    def selectable(self):
148
        """Make this a "selectable" widget.
149
        This overrides the method from urwid.FlowWidget."""
150
        return True
151
    
152
    def rows(self, (maxcol,), focus=False):
153
        """How many rows this widget will occupy might depend on
154
        whether we have focus or not.
155
        This overrides the method from urwid.FlowWidget"""
156
        return self.current_widget(focus).rows((maxcol,), focus=focus)
157
    
158
    def current_widget(self, focus=False):
159
        if focus or self.opened:
160
            return self._focus_widget
161
        return self._widget
162
    
163
    def update(self):
164
        "Called when what is visible on the screen should be updated."
165
        # How to add standout mode to a style
166
        with_standout = { u"normal": u"standout",
167
                          u"bold": u"bold-standout",
168
                          u"underline-blink":
169
                              u"underline-blink-standout",
170
                          u"bold-underline-blink":
171
                              u"bold-underline-blink-standout",
172
                          }
173
        
174
        # Rebuild focus and non-focus widgets using current properties
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
175
        self._text = (u'%(name)s: %(enabled)s'
176
                      % { u"name": self.properties[u"name"],
177
                          u"enabled":
178
                              (u"enabled"
179
                               if self.properties[u"enabled"]
180
                               else u"DISABLED")})
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
181
        if not urwid.supports_unicode():
182
            self._text = self._text.encode("ascii", "replace")
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
183
        textlist = [(u"normal", self._text)]
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
184
        self._text_widget.set_text(textlist)
185
        self._focus_text_widget.set_text([(with_standout[text[0]],
186
                                           text[1])
187
                                          if isinstance(text, tuple)
188
                                          else text
189
                                          for text in textlist])
190
        self._widget = self._text_widget
191
        self._focus_widget = urwid.AttrWrap(self._focus_text_widget,
192
                                            "standout")
193
        # Run update hook, if any
194
        if self.update_hook is not None:
195
            self.update_hook()
196
    
197
    def delete(self):
198
        if self.delete_hook is not None:
199
            self.delete_hook(self)
200
    
201
    def render(self, (maxcol,), focus=False):
202
        """Render differently if we have focus.
203
        This overrides the method from urwid.FlowWidget"""
204
        return self.current_widget(focus).render((maxcol,),
205
                                                 focus=focus)
206
    
207
    def keypress(self, (maxcol,), key):
208
        """Handle keys.
209
        This overrides the method from urwid.FlowWidget"""
210
        if key == u"e" or key == u"+":
211
            self.proxy.Enable()
212
        elif key == u"d" or key == u"-":
213
            self.proxy.Disable()
408 by Teddy Hogeborn
* debian/rules: Only set BROKEN_PIE if binutils is a specific range of
214
        elif key == u"r" or key == u"_" or key == u"ctrl k":
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
215
            self.server_proxy_object.RemoveClient(self.proxy
216
                                                  .object_path)
217
        elif key == u"s":
218
            self.proxy.StartChecker()
407 by Teddy Hogeborn
* mandos-monitor (MandosClientWidget): Change "StopChecker" key to "S"
219
        elif key == u"S":
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
220
            self.proxy.StopChecker()
407 by Teddy Hogeborn
* mandos-monitor (MandosClientWidget): Change "StopChecker" key to "S"
221
        elif key == u"C":
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
222
            self.proxy.CheckedOK()
223
        # xxx
224
#         elif key == u"p" or key == "=":
225
#             self.proxy.pause()
226
#         elif key == u"u" or key == ":":
227
#             self.proxy.unpause()
228
#         elif key == u"RET":
229
#             self.open()
230
        else:
231
            return key
232
    
233
    def property_changed(self, property=None, value=None,
234
                         *args, **kwargs):
235
        """Call self.update() if old value is not new value.
236
        This overrides the method from MandosClientPropertyCache"""
237
        property_name = unicode(property)
238
        old_value = self.properties.get(property_name)
239
        super(MandosClientWidget, self).property_changed(
240
            property=property, value=value, *args, **kwargs)
241
        if self.properties.get(property_name) != old_value:
242
            self.update()
243
244
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
245
class ConstrainedListBox(urwid.ListBox):
246
    """Like a normal urwid.ListBox, but will consume all "up" or
247
    "down" key presses, thus not allowing any containing widgets to
248
    use them as an excuse to shift focus away from this widget.
249
    """
250
    def keypress(self, (maxcol, maxrow), key):
251
        ret = super(ConstrainedListBox, self).keypress((maxcol, maxrow), key)
252
        if ret in (u"up", u"down"):
253
            return
254
        return ret
255
256
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
257
class UserInterface(object):
258
    """This is the entire user interface - the whole screen
259
    with boxes, lists of client widgets, etc.
260
    """
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
261
    def __init__(self, max_log_length=1000):
262
        DBusGMainLoop(set_as_default=True)
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
263
        
264
        self.screen = urwid.curses_display.Screen()
265
        
266
        self.screen.register_palette((
267
                (u"normal",
268
                 u"default", u"default", None),
269
                (u"bold",
270
                 u"default", u"default", u"bold"),
271
                (u"underline-blink",
272
                 u"default", u"default", u"underline"),
273
                (u"standout",
274
                 u"default", u"default", u"standout"),
275
                (u"bold-underline-blink",
276
                 u"default", u"default", (u"bold", u"underline")),
277
                (u"bold-standout",
278
                 u"default", u"default", (u"bold", u"standout")),
279
                (u"underline-blink-standout",
280
                 u"default", u"default", (u"underline", u"standout")),
281
                (u"bold-underline-blink-standout",
282
                 u"default", u"default", (u"bold", u"underline",
283
                                          u"standout")),
284
                ))
285
        
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
286
        if urwid.supports_unicode():
408 by Teddy Hogeborn
* debian/rules: Only set BROKEN_PIE if binutils is a specific range of
287
            self.divider = u"─" # \u2500
288
            #self.divider = u"━" # \u2501
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
289
        else:
290
            #self.divider = u"-" # \u002d
291
            self.divider = u"_" # \u005f
292
        
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
293
        self.screen.start()
294
        
295
        self.size = self.screen.get_cols_rows()
296
        
297
        self.clients = urwid.SimpleListWalker([])
298
        self.clients_dict = {}
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
299
        
300
        # We will add Text widgets to this list
301
        self.log = []
302
        self.max_log_length = max_log_length
303
        
304
        # We keep a reference to the log widget so we can remove it
305
        # from the ListWalker without it getting destroyed
306
        self.logbox = ConstrainedListBox(self.log)
307
        
308
        # This keeps track of whether self.uilist currently has
309
        # self.logbox in it or not
310
        self.log_visible = True
311
        self.log_wrap = u"any"
312
        
313
        self.rebuild()
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
314
        self.log_message_raw((u"bold",
315
                              u"Mandos Monitor version " + version))
316
        self.log_message_raw((u"bold",
317
                              u"q: Quit  ?: Help"))
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
318
        
319
        self.busname = domain + '.Mandos'
320
        self.main_loop = gobject.MainLoop()
321
        self.bus = dbus.SystemBus()
322
        mandos_dbus_objc = self.bus.get_object(
323
            self.busname, u"/", follow_name_owner_changes=True)
324
        self.mandos_serv = dbus.Interface(mandos_dbus_objc,
325
                                          dbus_interface
326
                                          = server_interface)
327
        try:
328
            mandos_clients = (self.mandos_serv
329
                              .GetAllClientsWithProperties())
330
        except dbus.exceptions.DBusException:
331
            mandos_clients = dbus.Dictionary()
332
        
333
        (self.mandos_serv
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
334
         .connect_to_signal(u"ClientRemoved",
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
335
                            self.find_and_remove_client,
336
                            dbus_interface=server_interface,
337
                            byte_arrays=True))
338
        (self.mandos_serv
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
339
         .connect_to_signal(u"ClientAdded",
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
340
                            self.add_new_client,
341
                            dbus_interface=server_interface,
342
                            byte_arrays=True))
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
343
        (self.mandos_serv
344
         .connect_to_signal(u"ClientNotFound",
345
                            self.client_not_found,
346
                            dbus_interface=server_interface,
347
                            byte_arrays=True))
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
348
        for path, client in mandos_clients.iteritems():
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
349
            client_proxy_object = self.bus.get_object(self.busname,
350
                                                      path)
351
            self.add_client(MandosClientWidget(server_proxy_object
352
                                               =self.mandos_serv,
353
                                               proxy_object
354
                                               =client_proxy_object,
355
                                               properties=client,
356
                                               update_hook
357
                                               =self.refresh,
358
                                               delete_hook
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
359
                                               =self.remove_client,
360
                                               logger
361
                                               =self.log_message),
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
362
                            path=path)
363
    
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
364
    def client_not_found(self, fingerprint, address):
365
        self.log_message((u"Client with address %s and fingerprint %s"
366
                          u" could not be found" % (address,
367
                                                    fingerprint)))
368
    
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
369
    def rebuild(self):
370
        """This rebuilds the User Interface.
371
        Call this when the widget layout needs to change"""
372
        self.uilist = []
373
        #self.uilist.append(urwid.ListBox(self.clients))
374
        self.uilist.append(urwid.Frame(ConstrainedListBox(self.clients),
375
                                       #header=urwid.Divider(),
376
                                       header=None,
377
                                       footer=urwid.Divider(div_char=self.divider)))
378
        if self.log_visible:
379
            self.uilist.append(self.logbox)
380
            pass
381
        self.topwidget = urwid.Pile(self.uilist)
382
    
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
383
    def log_message(self, message):
384
        timestamp = datetime.datetime.now().isoformat()
385
        self.log_message_raw(timestamp + u": " + message)
386
    
387
    def log_message_raw(self, markup):
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
388
        """Add a log message to the log buffer."""
389
        self.log.append(urwid.Text(markup, wrap=self.log_wrap))
390
        if (self.max_log_length
391
            and len(self.log) > self.max_log_length):
392
            del self.log[0:len(self.log)-self.max_log_length-1]
408 by Teddy Hogeborn
* debian/rules: Only set BROKEN_PIE if binutils is a specific range of
393
        self.logbox.set_focus(len(self.logbox.body.contents),
394
                              coming_from=u"above")
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
395
        self.refresh()
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
396
    
397
    def toggle_log_display(self):
398
        """Toggle visibility of the log buffer."""
399
        self.log_visible = not self.log_visible
400
        self.rebuild()
401
        self.log_message(u"Log visibility changed to: "
402
                         + unicode(self.log_visible))
403
    
404
    def change_log_display(self):
405
        """Change type of log display.
406
        Currently, this toggles wrapping of text lines."""
407
        if self.log_wrap == u"clip":
408
            self.log_wrap = u"any"
409
        else:
410
            self.log_wrap = u"clip"
411
        for textwidget in self.log:
412
            textwidget.set_wrap_mode(self.log_wrap)
413
        self.log_message(u"Wrap mode: " + self.log_wrap)
414
    
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
415
    def find_and_remove_client(self, path, name):
416
        """Find an client from its object path and remove it.
417
        
418
        This is connected to the ClientRemoved signal from the
419
        Mandos server object."""
420
        try:
421
            client = self.clients_dict[path]
422
        except KeyError:
423
            # not found?
424
            return
425
        self.remove_client(client, path)
426
    
427
    def add_new_client(self, path, properties):
428
        client_proxy_object = self.bus.get_object(self.busname, path)
429
        self.add_client(MandosClientWidget(server_proxy_object
430
                                           =self.mandos_serv,
431
                                           proxy_object
432
                                           =client_proxy_object,
433
                                           properties=properties,
434
                                           update_hook
435
                                           =self.refresh,
436
                                           delete_hook
437
                                           =self.remove_client),
438
                        path=path)
439
    
440
    def add_client(self, client, path=None):
441
        self.clients.append(client)
442
        if path is None:
443
            path = client.proxy.object_path
444
        self.clients_dict[path] = client
445
        self.clients.sort(None, lambda c: c.properties[u"name"])
446
        self.refresh()
447
    
448
    def remove_client(self, client, path=None):
449
        self.clients.remove(client)
450
        if path is None:
451
            path = client.proxy.object_path
452
        del self.clients_dict[path]
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
453
        if not self.clients_dict:
454
            # Work around bug in Urwid 0.9.8.3 - if a SimpleListWalker
455
            # is completely emptied, we need to recreate it.
456
            self.clients = urwid.SimpleListWalker([])
457
            self.rebuild()
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
458
        self.refresh()
459
    
460
    def refresh(self):
461
        """Redraw the screen"""
462
        canvas = self.topwidget.render(self.size, focus=True)
463
        self.screen.draw_screen(self.size, canvas)
464
    
465
    def run(self):
466
        """Start the main loop and exit when it's done."""
467
        self.refresh()
468
        self._input_callback_tag = (gobject.io_add_watch
469
                                    (sys.stdin.fileno(),
470
                                     gobject.IO_IN,
471
                                     self.process_input))
472
        self.main_loop.run()
473
        # Main loop has finished, we should close everything now
474
        gobject.source_remove(self._input_callback_tag)
475
        self.screen.stop()
476
    
477
    def stop(self):
478
        self.main_loop.quit()
479
    
480
    def process_input(self, source, condition):
481
        keys = self.screen.get_input()
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
482
        translations = { u"ctrl n": u"down",      # Emacs
483
                         u"ctrl p": u"up",        # Emacs
484
                         u"ctrl v": u"page down", # Emacs
485
                         u"meta v": u"page up",   # Emacs
486
                         u" ": u"page down",      # less
487
                         u"f": u"page down",      # less
488
                         u"b": u"page up",        # less
489
                         u"j": u"down",           # vi
490
                         u"k": u"up",             # vi
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
491
                         }
492
        for key in keys:
493
            try:
494
                key = translations[key]
495
            except KeyError:    # :-)
496
                pass
497
            
498
            if key == u"q" or key == u"Q":
499
                self.stop()
500
                break
501
            elif key == u"window resize":
502
                self.size = self.screen.get_cols_rows()
503
                self.refresh()
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
504
            elif key == u"\f":  # Ctrl-L
505
                self.refresh()
506
            elif key == u"l" or key == u"D":
507
                self.toggle_log_display()
508
                self.refresh()
509
            elif key == u"w" or key == u"i":
510
                self.change_log_display()
511
                self.refresh()
408 by Teddy Hogeborn
* debian/rules: Only set BROKEN_PIE if binutils is a specific range of
512
            elif key == u"?" or key == u"f1" or key == u"esc":
407 by Teddy Hogeborn
* mandos-monitor (MandosClientWidget): Change "StopChecker" key to "S"
513
                if not self.log_visible:
514
                    self.log_visible = True
515
                    self.rebuild()
409 by Teddy Hogeborn
* mandos (MandosServer.handle_ipc): Better log message.
516
                self.log_message_raw((u"bold",
517
                                      u"  ".
518
                                      join((u"q: Quit",
519
                                            u"?: Help",
520
                                            u"l: Log window toggle",
521
                                            u"TAB: Switch window",
522
                                            u"w: Wrap (log)"))))
523
                self.log_message_raw((u"bold",
524
                                      u"  "
525
                                      .join((u"Clients:",
526
                                             u"e: Enable",
527
                                             u"d: Disable",
528
                                             u"r: Remove",
529
                                             u"s: Start new checker",
530
                                             u"S: Stop checker",
531
                                             u"C: Checker OK"))))
405 by Teddy Hogeborn
* mandos-monitor (MandosClientPropertyCache): Remove conversion of
532
                self.refresh()
533
            elif key == u"tab":
534
                if self.topwidget.get_focus() is self.logbox:
535
                    self.topwidget.set_focus(0)
536
                else:
537
                    self.topwidget.set_focus(self.logbox)
538
                self.refresh()
407 by Teddy Hogeborn
* mandos-monitor (MandosClientWidget): Change "StopChecker" key to "S"
539
            #elif (key == u"end" or key == u"meta >" or key == u"G"
540
            #      or key == u">"):
541
            #    pass            # xxx end-of-buffer
542
            #elif (key == u"home" or key == u"meta <" or key == u"g"
543
            #      or key == u"<"):
544
            #    pass            # xxx beginning-of-buffer
545
            #elif key == u"ctrl e" or key == u"$":
546
            #    pass            # xxx move-end-of-line
547
            #elif key == u"ctrl a" or key == u"^":
548
            #    pass            # xxx move-beginning-of-line
549
            #elif key == u"ctrl b" or key == u"meta (" or key == u"h":
550
            #    pass            # xxx left
551
            #elif key == u"ctrl f" or key == u"meta )" or key == u"l":
552
            #    pass            # xxx right
553
            #elif key == u"a":
554
            #    pass            # scroll up log
555
            #elif key == u"z":
556
            #    pass            # scroll down log
404 by Teddy Hogeborn
* mandos-monitor: New prototype version of interactive server
557
            elif self.topwidget.selectable():
558
                self.topwidget.keypress(self.size, key)
559
                self.refresh()
560
        return True
561
562
ui = UserInterface()
563
try:
564
    ui.run()
565
except:
566
    ui.screen.stop()
567
    raise