No need to specify all copyright years, they are implied by specifying the first one
[polysh.git] / gsh / callbacks.py
blob678f7bb0cae8f8e1ae75ca6a231e1b317e6eb7b8
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2008 Guillaume Chazarain <guichaz@gmail.com>
19 # Gsh uses specially crafted strings to communicate out of band data with remote
20 # shells. This includes detecting the shell prompt, and other events to detect.
21 # These strings are built and sent in two parts, the remote shell should send
22 # back the concatenation of these two strings to trigger the callback. This is
23 # to insure that the sending of the trigger to the remote shell does not trigger
24 # the callback.
26 # Example: The trigger FOOBAR could be split into FOO and BAR and sent as
27 # echo "FOO""BAR" so that the sent string does not contain FOOBAR.
29 import random
31 DIGITS_LETTERS = map(str, range(10)) + \
32 map(chr, range(ord('a'), ord('z') + 1)) + \
33 map(chr, range(ord('A'), ord('Z') + 1))
35 def random_string(length):
36 def random_char():
37 return DIGITS_LETTERS[random.randint(0, len(DIGITS_LETTERS) - 1)]
38 return ''.join(map(lambda i: random_char(), xrange(length)))
40 COMMON_PREFIX = 'gsh-%s:' % random_string(5)
41 NR_GENERATED_TRIGGERS = 0
43 # {'random_string()': (function, repeat)}
44 CALLBACKS = {}
46 def add(name, function, repeat):
47 name = name.replace('/', '_')
48 global NR_GENERATED_TRIGGERS
49 nr = NR_GENERATED_TRIGGERS
50 NR_GENERATED_TRIGGERS += 1
51 trigger = '%s%s:%s:%d/' % (COMMON_PREFIX, name, random_string(5), nr)
52 CALLBACKS[trigger] = (function, repeat)
53 trigger1 = trigger[:len(COMMON_PREFIX)/2]
54 trigger2 = trigger[len(trigger1):]
55 return trigger1, trigger2
57 def any_in(data):
58 return COMMON_PREFIX in data
60 def process(line):
61 start = line.find(COMMON_PREFIX)
62 if start < 0:
63 return False
65 end = line.find('/', start) + 1
66 if end <= 0:
67 return False
69 trigger = line[start:end]
70 callback, repeat = CALLBACKS.get(trigger, (None, True))
71 if not callback:
72 return False
74 if not repeat:
75 del CALLBACKS[trigger]
77 callback(line[end:].strip())
78 return True