#!/usr/bin/env python class Request: Commands = {} @staticmethod def Register(name): def decorate(cls): Request.Commands[name] = cls return cls return decorate @staticmethod def ReadCommand(shell): cmd = shell.read_line().strip() request = Request.Commands[cmd](shell) return request def __init__(self, shell): self.shell = shell def read_params(self): pass def execute(self): raise NotImplementedError() @Request.Register("noop") class NoopRequest(Request): def execute(self): pass @Request.Register("ping") class PingRequest(Request): def execute(self): self.shell.status("ALIVE") @Request.Register("exit") class ExitRequest(Request): def execute(self): self.shell.exit() @Request.Register("glob") class GlobRequest(Request): def read_params(self): self.pattern = self.shell.read_line() def execute(self): from glob import glob results = glob(self.pattern) self.shell.write("%i\n" % len(results)) for result in results: self.shell.write(result+"\n") @Request.Register("exec") class ExecRequest(Request): def read_params(self): self.cmd = self.shell.read_line() def execute(self): from subprocess import Popen, PIPE proc = Popen(self.cmd, shell=True, stdout=PIPE, stderr=PIPE, bufsize=-1) stdout, stderr = proc.communicate() self.shell.write("%i\n" % proc.returncode) self.shell.write_blob(stdout) self.shell.write_blob(stderr) class Shell: def __init__(self, input_stream, output_stream, status_stream, bork_action = None): self.__input_stream__ = input_stream self.__output_stream__ = output_stream self.__status_stream__ = status_stream self.__bork_action__ = bork_action or self.exit self.__exit__ = False self.__req_counter__ = 0 def loop(self): while self.__exit__ == False: self.show_prompt() try: request = Request.ReadCommand(self) except KeyboardInterrupt: self.exit() except KeyError: self.status("UNKNOWN COMMAND"); self.bork() else: try: request.read_params() except KeyboardInterrupt: pass else: self.__req_counter__ += 1 try: request.execute() except KeyboardInterrupt: self.status("INTERRUPTED"); def exit(self): self.__exit__ = True def bork(self): self.__bork_action__() def show_prompt(self): self.write("#%i#\n" % self.__req_counter__) def status(self, str): print >> self.__status_stream__, str def write(self, msg): self.__output_stream__.write(msg) def write_blob(self, blob): self.write("%i\n" % len(blob)) self.write(str(blob)+"\n") def read_line(self): while True: try: return self.__input_stream__.readline().strip() except IOError: pass def read_blob(self, length): try: blob = self.__input_stream__.read(length) assert self.__input_stream__.read(1) == "\n" except: raise IOError() else: return blob if __name__ == "__main__": from sys import stdin, stdout, stderr, exit from signal import signal, SIGUSR1 def handler(signum, frame): print >> stderr, "ALIVE" signal(SIGUSR1, handler) def bork(): exit(-1) Shell(stdin, stdout, stderr, bork_action = bork).loop()