From 2a86cb5859e20494a77453228f7e9a0a06f8461c Mon Sep 17 00:00:00 2001 From: henryk Date: Thu, 29 Sep 2005 14:41:20 +0000 Subject: [PATCH] Completion git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@14 f711b948-2313-0410-aaa9-d29f33439f0b --- cyberflex-shell.py | 194 ++++++++++++++++++++++++++++++--------------- 1 file changed, 128 insertions(+), 66 deletions(-) diff --git a/cyberflex-shell.py b/cyberflex-shell.py index e677027..4eb73e4 100755 --- a/cyberflex-shell.py +++ b/cyberflex-shell.py @@ -1,77 +1,139 @@ #!/usr/bin/env python # -*- coding: iso-8859-1 -*- -import pycsc, utils, cards, os, readline, re, binascii, sys +import pycsc, utils, cards, os, re, binascii, sys, exceptions -histfile = os.path.join(os.environ["HOME"], ".cyberflex-shell.history") try: - readline.read_history_file(histfile) -except IOError: - pass -import atexit -atexit.register(readline.write_history_file, histfile) -del os, histfile + import readline +except ImportError: + print "No readline available" -readline.parse_and_bind("tab: complete") - - -readerName = pycsc.listReader()[0] -newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':pycsc.SCARD_STATE_UNAWARE}]) - -print "Cyberflex shell" -print "Using reader: %s" % readerName -print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") - -if not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT: - print "Please insert card ..." - - while not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT \ - or newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: - - newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':newState[0]['EventState']}]) - - if newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: - print "Card is mute, please retry ..." - - print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") - -print "ATR: %s" % utils.hexdump(newState[0]['Atr'], short = True) -card_class = cards.find_class(newState[0]['Atr']) - -card = card_class() - -line = "" -apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I) -while line != "exit": +if sys.modules.has_key("readline"): + histfile = os.path.join(os.environ["HOME"], ".cyberflex-shell.history") try: - line = raw_input("%s > " % card.get_prompt()) - except EOFError: - print - break + readline.read_history_file(histfile) + except IOError: + pass + import atexit + atexit.register(readline.write_history_file, histfile) + del os, histfile - line = line.strip() - if line == "": - continue + readline.parse_and_bind("tab: complete") - parts = line.split() - cmd = parts[0] - if card.COMMANDS.has_key(cmd.lower()): - cmdspec = card.COMMANDS[cmd.lower()] - try: - cmdspec[0](card, *parts[1:]) - except Exception: - exctype, value = sys.exc_info()[:2] - print "%s: %s" % (exctype, value) +class Cyberflex_Shell_Completer: + def __init__(self, *commands): + self.commands = commands + self.card = None + def set_card(self, card): + self.card = card + def complete(self, text, state): + found = -1 + def check(text, state, cmd, found): + if text == cmd[:len(text)]: + found = found+1 + if found == state: + return (found, cmd) + else: + return (found, None) - elif apduregex.match(line): - ## Might be an APDU - apdu = binascii.a2b_hex("".join(line.split())) - try: - response = card.send_apdu(apdu) - print utils.hexdump(response) - except Exception: - exctype, value = sys.exc_info()[:2] - print "%s: %s" % (exctype, value) + if self.card is not None: + for (cmd, cmdspec) in self.card.COMMANDS.items(): + (found, retval) = check(text, state, cmd, found) + if retval is not None: + return retval + for cmdset in self.commands: + for (cmd, cmdspec) in cmdset.items(): + (found, retval) = check(text, state, cmd, found) + if retval is not None: + return retval - else: - print "Unknown command" + return False + +def cmd_exit(card, *args): + sys.exit() + +COMMANDS = { + "exit": (cmd_exit, "exit", + """Exit the shell.""") +} + +if __name__ == "__main__": + + readerName = pycsc.listReader()[0] + newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':pycsc.SCARD_STATE_UNAWARE}]) + + print "Cyberflex shell" + print "Using reader: %s" % readerName + print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") + + if not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT: + print "Please insert card ..." + + while not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT \ + or newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: + + newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':newState[0]['EventState']}]) + + if newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: + print "Card is mute, please retry ..." + + print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") + + print "ATR: %s" % utils.hexdump(newState[0]['Atr'], short = True) + card_class = cards.find_class(newState[0]['Atr']) + + card = card_class() + + if sys.modules.has_key("readline"): + completer = Cyberflex_Shell_Completer(COMMANDS) + completer.set_card(card) + readline.set_completer(completer.complete) + + + line = "" + apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I) + while True: + try: + line = raw_input("%s > " % card.get_prompt()) + except EOFError: + print + break + + line = line.strip() + if line == "": + continue + + parts = line.split() + cmd = parts[0] + if card.COMMANDS.has_key(cmd.lower()): + cmdspec = card.COMMANDS[cmd.lower()] + try: + cmdspec[0](card, *parts[1:]) + except Exception: + exctype, value = sys.exc_info()[:2] + if exctype == exceptions.SystemExit: + raise exctype, value + print "%s: %s" % (exctype, value) + + elif COMMANDS.has_key(cmd.lower()): + cmdspec = COMMANDS[cmd.lower()] + try: + cmdspec[0](card, *parts[1:]) + except Exception: + exctype, value = sys.exc_info()[:2] + if exctype == exceptions.SystemExit: + raise exctype, value + print "%s: %s" % (exctype, value) + + elif apduregex.match(line): + ## Might be an APDU + apdu = binascii.a2b_hex("".join(line.split())) + try: + response = card.send_apdu(apdu) + print utils.hexdump(response) + except Exception: + exctype, value = sys.exc_info()[:2] + print "%s: %s" % (exctype, value) + + else: + print "Unknown command"