Example #1
0
 def _configChangeHook(self, ses, name, value, newvalue):
     exported.hook_spam("config_change_hook", {
         "session": ses,
         "name": name,
         "oldvalue": value,
         "newvalue": newvalue
     })
Example #2
0
  def connect(self, host, port, sessionname):
    """
    Takes in a host and a port and connects the socket.

    @param host: the host to connect to
    @type  host: string

    @param port: the port to connect at
    @type  port: int

    @param sessionname: the name of the new session
    @type  sessionname: string
    """
    if not self._sock:
      sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      sock.connect((host, port))
      sock.setblocking(1)

      self._host = host
      self._port = port
      self._sock = sock
      self._sessionname = sessionname

      ses = exported.get_session(sessionname)

      exported.hook_spam("connect_hook", \
              {"session": ses, "host": host, "port": port})
    else:
      raise Exception("Connection already exists.")
Example #3
0
    def connect(self, host, port, sessionname):
        """
    Takes in a host and a port and connects the socket.

    @param host: the host to connect to
    @type  host: string

    @param port: the port to connect at
    @type  port: int

    @param sessionname: the name of the new session
    @type  sessionname: string
    """
        if not self._sock:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((host, port))
            sock.setblocking(1)

            self._host = host
            self._port = port
            self._sock = sock
            self._sessionname = sessionname

            ses = exported.get_session(sessionname)

            exported.hook_spam("connect_hook", \
                    {"session": ses, "host": host, "port": port})
        else:
            raise Exception("Connection already exists.")
Example #4
0
  def shutdown(self, args):
    """
    Shuts down the session, shuts down the underlying SocketCommunicator.

    @param args: the args tuple for the shutdown_hook.
    @type  args: tuple
    """
    if len(args) > 0:
      quiet = 1
    else:
      quiet = 0

    # unregister with the shutdown hook
    # exported.hook_unregister("shutdown_hook", self.shutdown)
    if self.getName() != "common":
      if quiet == 0:
        event.OutputEvent("Session %s disconnected.\n\"#zap %s\" to kill the session.\n" % (self._name, self._name)).enqueue()
      exported.hook_spam("disconnect_hook", {"session": self, "host": self._host,  "port": self._port})

      if self._socket:
        self._socket.shutdown()

      self._host = None
      self._port = 0
      self._socket = None
Example #5
0
  def writeSocket(self, message, tag=None):
    """
    Writes data to the socket.

    @param message: the data to be written to the mud
    @type  message: string

    @param tag: Used to tag data being sent to the mud for 
        identification when it comes out of the to_mud_hook.  
        Simply passed through as-is by lyntin internals.
    @type  tag: varies
    """
    for line in message.strip().split("\n"):
      exported.hook_spam("to_mud_hook", {"session": self, "data": line, "tag": tag})

    if self._socket:
      retval = self._socket.write(str(message))
      if retval:
        exported.write_error("socket write: %s" % retval)

    else:
      # if we don't have a socket then we can't do any non-lyntin-command
      # stuff.
      exported.write_error("No connection.  Create a session.\n(See also: #help, #help session)")
      return
Example #6
0
  def get_completion_list(self, text='', position=None):
    """
    Returns the completion list. Rebuilds the list if it is empty.

    @param text: the text to be completed
    @type  text: string

    @param position: cursor position in the text
    @type  position: int
    
    @returns: all possible completion pairs list [(newtext, newposition)]
    @rtype:   [(string, int)]
    """
    if not self.completion_list_:
      #
      # Rebuild the completion list if it is empty after reset.
      #
      if position==None or position<0 or position>len(text):
        position = len(text)
      #
      # Gather all the completions from registered completers:
      #
      exported.hook_spam("completer_hook",
                         { 'text': text, 'position': position },
                         self._completion_mapping_helper
                        )
      # put an anchor at the end of list
      self.completion_list_.append((text, position))
    return self.completion_list_
Example #7
0
  def get_completion_list(self, text='', position=None):
    """
    Returns the completion list. Rebuilds the list if it is empty.

    @param text: the text to be completed
    @type  text: string

    @param position: cursor position in the text
    @type  position: int
    
    @returns: all possible completion pairs list [(newtext, newposition)]
    @rtype:   [(string, int)]
    """
    if not self.completion_list_:
      #
      # Rebuild the completion list if it is empty after reset.
      #
      if position==None or position<0 or position>len(text):
        position = len(text)
      #
      # Gather all the completions from registered completers:
      #
      exported.hook_spam("completer_hook",
                         { 'text': text, 'position': position },
                         self._completion_mapping_helper
                        )
      # put an anchor at the end of list
      self.completion_list_.append((text, position))
    return self.completion_list_
Example #8
0
    def writeSocket(self, message, tag=None):
        """
    Writes data to the socket.

    @param message: the data to be written to the mud
    @type  message: string

    @param tag: Used to tag data being sent to the mud for 
        identification when it comes out of the to_mud_hook.  
        Simply passed through as-is by lyntin internals.
    @type  tag: varies
    """
        for line in message.strip().split("\n"):
            exported.hook_spam("to_mud_hook", {
                "session": self,
                "data": line,
                "tag": tag
            })

        if self._socket:
            retval = self._socket.write(str(message))
            if retval:
                exported.write_error("socket write: %s" % retval)

        else:
            # if we don't have a socket then we can't do any non-lyntin-command
            # stuff.
            exported.write_error(
                "No connection.  Create a session.\n(See also: #help, #help session)"
            )
            return
Example #9
0
    def shutdown(self, args):
        """
    Shuts down the session, shuts down the underlying SocketCommunicator.

    @param args: the args tuple for the shutdown_hook.
    @type  args: tuple
    """
        if len(args) > 0:
            quiet = 1
        else:
            quiet = 0

        # unregister with the shutdown hook
        # exported.hook_unregister("shutdown_hook", self.shutdown)
        if self.getName() != "common":
            if quiet == 0:
                event.OutputEvent(
                    "Session %s disconnected.\n\"#zap %s\" to kill the session.\n"
                    % (self._name, self._name)).enqueue()
            exported.hook_spam("disconnect_hook", {
                "session": self,
                "host": self._host,
                "port": self._port
            })

            if self._socket:
                self._socket.shutdown()

            self._host = None
            self._port = 0
            self._socket = None
Example #10
0
def bell_cmd(ses, words, input):
    """
  Kicks off the bell for a given session.  Anything registered
  with the bell_hook will get tickled.

  category: commands
  """
    exported.hook_spam("bell_hook", {"session": ses})
Example #11
0
 def _varChangeHook(self, var, old, new):
   """
   This calls the variable_change_hook.  It allows other modules to
   know when variable values are changed so that they can handle
   those changes accordingly.
   """
   exported.hook_spam("variable_change_hook", 
         {"session": self, "variable": var, "oldvalue": old, "newvalue": new})
Example #12
0
def bell_cmd(ses, words, input):
  """
  Kicks off the bell for a given session.  Anything registered
  with the bell_hook will get tickled.

  category: commands
  """
  exported.hook_spam("bell_hook", {"session": ses})
Example #13
0
  def execute(self):
    """ Execute."""
    exported.hook_spam(*(self._vargs), **(self._nargs))

# Local variables:
# mode:python
# py-indent-offset:2
# tab-width:2
# End:
Example #14
0
  def set_current_session(self, newsession):    
    """
    Changes the current session to another session.

    @param newsession: the session to change to
    @type  newsession: session.Session instance
    """
    previous_session = self._current_session
    self._current_session = newsession
    exported.hook_spam("session_change_hook", {"new": newsession,
                                      "previous": previous_session})
    exported.write_message("%s now current session." % newsession.getName())
Example #15
0
  def set_current_session(self, newsession):    
    """
    Changes the current session to another session.

    @param newsession: the session to change to
    @type  newsession: session.Session instance
    """
    previous_session = self._current_session
    self._current_session = newsession
    exported.hook_spam("session_change_hook", {"new": newsession,
                                      "previous": previous_session})
    exported.write_message("%s now current session." % newsession.getName())
Example #16
0
 def _varChangeHook(self, var, old, new):
     """
 This calls the variable_change_hook.  It allows other modules to
 know when variable values are changed so that they can handle
 those changes accordingly.
 """
     exported.hook_spam("variable_change_hook", {
         "session": self,
         "variable": var,
         "oldvalue": old,
         "newvalue": new
     })
Example #17
0
  def tallyError(self):
    """
    Adds one to the error count.  If we see more than 20 errors, we shutdown.
    """
    self._errorcount = self._errorcount + 1
    exported.write_error("WARNING: Unhandled error encountered (%d out of %d)." 
                         % (self._errorcount, 20))
    exported.hook_spam("error_occurred_hook", {"count": self._errorcount})

    if self._errorcount > 20:
      exported.hook_spam("too_many_errors_hook", {})
      exported.write_error("Error count exceeded--shutting down.")
      sys.exit(0)
Example #18
0
  def tallyError(self):
    """
    Adds one to the error count.  If we see more than 20 errors, we shutdown.
    """
    self._errorcount = self._errorcount + 1
    exported.write_error("WARNING: Unhandled error encountered (%d out of %d)." 
                         % (self._errorcount, 20))
    exported.hook_spam("error_occurred_hook", {"count": self._errorcount})

    if self._errorcount > 20:
      exported.hook_spam("too_many_errors_hook", {})
      exported.write_error("Error count exceeded--shutting down.")
      sys.exit(0)
Example #19
0
def shutdown():
  """
  This gets called by the Python interpreter atexit.  The reason
  we do shutdown stuff here is we're more likely to catch things
  here than we are to let everything cycle through the 
  ShutdownEvent.  This should probably get fixed up at some point
  in the future.

  Do not call this elsewhere.
  """
  import exported
  try:
    exported.write_message("shutting down...  goodbye.")
  except:
    print "shutting down...  goodbye."
  exported.hook_spam("shutdown_hook", {})
Example #20
0
def shutdown():
    """
  This gets called by the Python interpreter atexit.  The reason
  we do shutdown stuff here is we're more likely to catch things
  here than we are to let everything cycle through the 
  ShutdownEvent.  This should probably get fixed up at some point
  in the future.

  Do not call this elsewhere.
  """
    import exported
    try:
        exported.write_message("shutting down...  goodbye.")
    except:
        print "shutting down...  goodbye."
    exported.hook_spam("shutdown_hook", {})
Example #21
0
  def writeUI(self, text):
    """
    Writes a message to the ui.

    This method uses a lock so that multiple threads can write
    to the ui without intersecting and crashing the python process.

    Theoretically you should use the exported module to write
    things to the ui--it calls this method.

    @param text: the message to write to the ui
    @type  text: string or ui.base.Message
    """
    self._ui_lock.acquire(1)
    try:
      exported.hook_spam("to_user_hook", {"message": text})
    finally:
      self._ui_lock.release()
Example #22
0
    def writeUI(self, text):
        """
    Writes a message to the ui.

    This method uses a lock so that multiple threads can write
    to the ui without intersecting and crashing the python process.

    Theoretically you should use the exported module to write
    things to the ui--it calls this method.

    @param text: the message to write to the ui
    @type  text: string or ui.base.Message
    """
        self._ui_lock.acquire(1)
        try:
            exported.hook_spam("to_user_hook", {"message": text})
        finally:
            self._ui_lock.release()
Example #23
0
    def write(self, data, convert=1):
        """
    Writes data to the mud after passing it through net_write_data_filter.

    @param data: the data to write to the socket
    @type  data: bytes

    @param convert: whether (1) or not (0) we should convert eol stuff to 
        CRLF and IAC to IAC IAC.
    @type  convert: boolean

    @raises Exception: if we have problems sending the data over the
        socket
    """
        data = data + b"\n"
        if convert:
            data = data.replace(b"\n", b"\r\n")

            if IAC in data:
                data = data.replace(IAC, IAC + IAC)

        if self._shutdownflag == 0:
            # run the data through the net_write_data_filter hook which
            # allows things like compressors and other data transformation
            # mechanisms to do their thing.
            spamargs = {
                "session": self._session,
                "data": data,
                "dataadj": data
            }
            spamargs = exported.hook_spam("net_write_data_filter",
                                          argmap=spamargs,
                                          mappingfunc=exported.filter_mapper)

            if spamargs == None:
                return
            else:
                data = spamargs["dataadj"]

            try:
                self._sock.send(data)

            except Exception as e:
                if self._shutdownflag == 0 and self._session:
                    self._session.shutdown(())
                    raise Exception(e)

            return None
Example #24
0
    def _filterIncomingData(self, data):
        """
    run the data through the net_read_data_filter hook which
    allows things like compressors and other data transformation
    mechanisms to do their thing.
    """
        # be careful--this catches both the '' and the None situations
        if not data:
            return data

        spamargs = {"session": self._session, "data": data, "dataadj": data}
        spamargs = exported.hook_spam("net_read_data_filter", argmap=spamargs, mappingfunc=exported.filter_mapper)

        if spamargs == None:
            data = ""
        else:
            data = spamargs["dataadj"]

        return data
Example #25
0
  def write(self, data, convert=1):
    """
    Writes data to the mud after passing it through net_write_data_filter.

    @param data: the data to write to the socket
    @type  data: string

    @param convert: whether (1) or not (0) we should convert eol stuff to
        CRLF and IAC to IAC IAC.
    @type  convert: boolean

    @raises Exception: if we have problems sending the data over the
        socket
    """
    if convert:
      data = data.replace("\n", "\r\n")

      if IAC in data:
        data = data.replace(IAC, IAC+IAC)

    if self._shutdownflag == 0:
      # run the data through the net_write_data_filter hook which
      # allows things like compressors and other data transformation
      # mechanisms to do their thing.
      spamargs = {"session": self._session, "data": data, "dataadj": data}
      spamargs = exported.hook_spam("net_write_data_filter", argmap=spamargs,
            mappingfunc=exported.filter_mapper)

      if spamargs == None:
        return
      else:
        data = spamargs["dataadj"]

      try:
        self._sock.send(data)

      except Exception, e:
        if self._shutdownflag == 0 and self._session:
          self._session.shutdown(())
          raise Exception(e)

      return None
Example #26
0
  def _filterIncomingData(self, data):
    """
    run the data through the net_read_data_filter hook which
    allows things like compressors and other data transformation
    mechanisms to do their thing.
    """
    # be careful--this catches both the '' and the None situations
    if not data:
      return data

    spamargs = {"session": self._session, "data": data, "dataadj": data}
    spamargs = exported.hook_spam("net_read_data_filter",
          argmap=spamargs, mappingfunc=exported.filter_mapper)

    if spamargs == None:
      data = ""
    else:
      data = spamargs["dataadj"]

    return data
Example #27
0
    def filter(self, args):
        """
    Takes in user command lines and handles commands that start
    with a Lyntin command character.

    @param args: (session, internal boolean, ..., current input text)
    @type  args: tuple

    @return: None if we handled the input, or the current input text if 
        we didn't
    @rtype:  None or string
    """
        ses = args["session"]
        internal = args["internal"]
        input = args["dataadj"]

        commandchar = self._engine.getConfigManager().get("commandchar")
        if len(input) > 1 and input.startswith(commandchar):
            input = input[1:]

            # splits out the command name from the rest of the command line
            words = input.split(" ", 1)

            # We want an empty argument list if there was one, don't want
            # array out-of-bounds issues
            if len(words) < 2: words.append("")

            # this checks to see if it's a special #@ command.
            if input.startswith("@"):
                self.getCommand("@")(ses, input.split(" "), input)
                if internal == 0: ses.prompt()
                return

            # this finds the first matching command and ends there.
            commands = self.getCommands()
            commands.sort()
            for mem in commands:
                command = None
                if mem.startswith("^"):
                    if re.compile(mem).search(words[0]):
                        command = self.getCommand(mem)
                else:
                    if mem.startswith(words[0]):
                        command = self.getCommand(mem)

                if command:
                    argumentparser = self.getArgParser(mem)
                    if argumentparser == None:
                        command(ses, input.split(" "), input)
                    else:
                        # for printing out the error message, we remove the ^
                        # from the command name if it's there.
                        fixedmem = mem
                        if len(fixedmem) > 0 and fixedmem.startswith("^"):
                            fixedmem = fixedmem[1:]

                        resolver = exported.hook_spam(
                            "default_resolver_hook", {
                                "session": ses,
                                "commandname": mem
                            },
                            mappingfunc=exported.query_mapper,
                            donefunc=exported.query_done)

                        try:
                            argdict = argumentparser.parse(words[1], resolver)
                            argdict["command"] = mem
                            command(ses, argdict, input)
                        except ValueError, e:
                            exported.write_error(
                                "%s: %s\nsyntax: %s%s %s" %
                                (fixedmem, e, commandchar, fixedmem,
                                 argumentparser.syntaxline))
                        except argparser.ParserException, e:
                            exported.write_error(
                                "%s: %s\nsyntax: %s%s %s" %
                                (fixedmem, e, commandchar, fixedmem,
                                 argumentparser.syntaxline))
                    if internal == 0:
                        ses.prompt()
                    break
Example #28
0
def main(defaultoptions={}):
  """
  This parses the command line arguments and makes sure they're all valid,
  instantiates a ui, does some setup, spins off an engine thread, and
  goes into the ui's mainloop.

  @param defaultoptions: the boot options to use.  we update the 
      config.options dict with these options--this is the easiest
      way to override the ui, moduledir, datadir, et al from a
      Lyntin run script.
  @type  defaultoptions: dict
  """
  try:
    import sys, os, traceback, ConfigParser
    from lyntin import config, event, utils, exported
    from lyntin.ui import base
    import locale

    locale.setlocale(locale.LC_ALL, '')

    config.options.update(defaultoptions)

    # read through options and arguments
    optlist = utils.parse_args(sys.argv[1:])

    for mem in optlist:
      if mem[0] == '--help':
        print constants.HELPTEXT
        sys.exit(0)

      elif mem[0] == '--version':
        print constants.VERSION
        sys.exit(0)

      elif mem[0] in ["--configuration", "-c"]:
        # ini files OVERRIDE the default options
        # they can provide multiple ini files, but each new
        # ini file will OVERRIDE the contents of the previous ini file
        # where the two files intersect.
        parser = ConfigParser.ConfigParser()
        parser.read([mem[1]])

        newoptions = {}
        for s in parser.sections():
          for o in parser.options(s):
            c = parser.get(s, o).split(",")
            if newoptions.has_key(o):
              newoptions[o] += c
            else:
              newoptions[o] = c
            
        config.options.update(newoptions)

      else:
        opt = mem[0]
        while opt.startswith("-"):
          opt = opt[1:]

        if len(opt) > 0:
          if config.options.has_key(opt):
            if type(config.options[opt]) is list:
              config.options[opt].append(mem[1])
            else:
              config.options[opt] = mem[1]
          else:
            config.options[opt] = [mem[1]]

    for mem in ["datadir", "ui", "commandchar"]:
      if config.options.has_key(mem) and type(config.options[mem]) is list:
        config.options[mem] = config.options[mem][0]

    # if they haven't set the datadir via the command line, then
    # we go see if they have a HOME in their environment variables....
    if not config.options["datadir"]:
      if os.environ.has_key("HOME"):
        config.options["datadir"] = os.environ["HOME"]
    config.options["datadir"] = utils.fixdir(config.options["datadir"])

    def on_shutdown():
      """
      This gets called by the Python interpreter atexit.  The reason
      we do shutdown stuff here is we're more likely to catch things
      here than we are to let everything cycle through the 
      ShutdownEvent.  This should probably get fixed up at some point
      in the future.
      """
      if not hasattr(sys, 'frozen'):
        sys.stderr.write("goodbye.\n")
      #exported.hook_spam("shutdown_hook", {})
    import atexit
    atexit.register(on_shutdown)

    # instantiate the engine
    Engine.instance = Engine()
    exported.myengine = Engine.instance
    Engine.instance._setupConfiguration()

    # instantiate the ui
    uiinstance = None
    try:
      uiname = str(config.options['ui'])
      modulename = uiname + "ui"
      uiinstance = base.get_ui(modulename)
      if not uiinstance:
        raise ValueError("No ui instance.")
    except Exception, e:
      print "Cannot start '%s': %s" % (uiname, e)
      traceback.print_exc()
      sys.exit(0)

    Engine.instance.setUI(uiinstance)

    # do some more silly initialization stuff
    # adds the .lyntinrc file to the readfile list if it exists.
    if config.options["datadir"]:
      lyntinrcfile = config.options["datadir"] + ".lyntinrc"
      if os.path.exists(lyntinrcfile):
        # we want the .lyntinrc file read in first, so then other
        # files can overwrite the contents therein
        config.options['readfile'].insert(0, lyntinrcfile)
  
    # import modules listed in modulesinit
    exported.write_message("Loading Lyntin modules.")
  
    try:
      import lyntin.modules
      lyntin.modules.load_modules()
    except:
      exported.write_traceback("Modules did not load correctly.")
      sys.exit(1)
  
    commandchar = Engine.instance._managers["config"].get("commandchar")

    # handle command files
    for mem in config.options['readfile']:
      exported.write_message("Reading in file " + mem)
      # we have to escape windows os separators because \ has a specific
      # meaning in the argparser
      mem = mem.replace("\\", "\\\\")
      exported.lyntin_command("%sread %s" % (commandchar, mem), internal=1)
  
    # spam the startup hook 
    exported.hook_spam("startup_hook", {})
  
    # we're done initialization!
    exported.write_message(constants.STARTUPTEXT)
    Engine.instance.writePrompt()

    engine_thread = Engine.instance.startthread("engine", Engine.instance.runengine)
    timer_thread = Engine.instance.startthread("timer", Engine.instance.runtimer)
    try:
      Engine.instance._ui.runui()
    finally:
      if not hasattr(sys, 'frozen'):
        sys.stderr.write("Shutting down...")
      event.ShutdownEvent().enqueue()
      engine_thread.join(10)
      timer_thread.join(10)
Example #29
0
 def _configChangeHook(self, ses, name, value, newvalue):
   exported.hook_spam("config_change_hook",
       {"session": ses, "name": name, "oldvalue": value, "newvalue": newvalue })
Example #30
0
  def filter(self, args):
    """
    Takes in user command lines and handles commands that start
    with a Lyntin command character.

    @param args: (session, internal boolean, ..., current input text)
    @type  args: tuple

    @return: None if we handled the input, or the current input text if 
        we didn't
    @rtype:  None or string
    """
    ses = args["session"]
    internal = args["internal"]
    input = args["dataadj"]

    commandchar = self._engine.getConfigManager().get("commandchar")
    if len(input) > 1 and input.startswith(commandchar):
      input = input[1:]

      # splits out the command name from the rest of the command line
      words = input.split(" ",1)

      # We want an empty argument list if there was one, don't want
      # array out-of-bounds issues       
      if len(words) < 2: words.append("")

      # this checks to see if it's a special #@ command.
      if input.startswith("@"):
        self.getCommand("@")(ses, input.split(" "), input)
        if internal==0: ses.prompt()
        return

      # this finds the first matching command and ends there.
      commands = self.getCommands()
      commands.sort()
      for mem in commands:
        command = None
        if mem.startswith("^"):
          if re.compile(mem).search(words[0]):
            command = self.getCommand(mem)
        else:
          if mem.startswith(words[0]):
            command = self.getCommand(mem)

        if command:
          argumentparser = self.getArgParser(mem)
          if argumentparser == None:
            command(ses, input.split(" "), input)
          else:
            # for printing out the error message, we remove the ^
            # from the command name if it's there.
            fixedmem = mem
            if len(fixedmem) > 0 and fixedmem.startswith("^"):
              fixedmem = fixedmem[1:]

            resolver = exported.hook_spam("default_resolver_hook", 
                                {"session": ses, "commandname": mem}, 
                                mappingfunc=exported.query_mapper, 
                                donefunc=exported.query_done)

            try:
              argdict = argumentparser.parse(words[1], resolver)
              argdict["command"]=mem
              command(ses, argdict, input)
            except ValueError, e:
              exported.write_error("%s: %s\nsyntax: %s%s %s" % 
                                   (fixedmem, e, commandchar, fixedmem,
                                    argumentparser.syntaxline))
            except argparser.ParserException, e:
              exported.write_error("%s: %s\nsyntax: %s%s %s" % 
                                   (fixedmem, e, commandchar, fixedmem,
                                    argumentparser.syntaxline))
          if internal == 0:
            ses.prompt()
          break
Example #31
0
  def handleUserData(self, input, internal=0, session=None ):
    """
    This handles input lines from the user in a session-less context.
    The engine.handleUserData deals with global stuff and then
    passes the modified input to the session for session-oriented
    handling.  The session can call this method again with
    expanded input--this method is considered recursive.

    internal tells whether to spam the input hook and
    things of that nature.

    @param input: the data from the user
    @type  input: string

    @param internal: whether this should be executed internally or not.
        0 if we should spam the input hook and record
        the input to the historymanager; 1 if we shouldn't
    @type  internal: boolean

    @param session: the session scoping to execute this user input in
    @type  session: session.Session instance

    @return: the commands that were actually executed (may not be
        exactly what the user typed--this is for the history manager)
    @rtype: string
    """ 
    if self._managers["config"].get("debugmode") == 1:
      exported.write_message("evaluating: %s" % input)

    inputlist = utils.split_commands(self._managers["config"].get("splitchar"), 
                                     input)
    if session == None:
      session = self._current_session

    historyitems = []
    commandchar = self._managers["config"].get("commandchar")
    for mem in inputlist:
      # mem = mem.strip()

      if len(mem) == 0:
        mem = commandchar + "cr"

      # if it's not internal we spam the hook with the raw input
      if internal == 0:
        exported.hook_spam("from_user_hook", {"data": mem})

      if mem.startswith("!"):
        memhistory = self.getManager("history").getHistoryItem(mem)
        if memhistory != None:
          self.handleUserData(memhistory, 1, session)
          historyitems.append(memhistory)
          continue

      # if it starts with a # it's a loop, session or command
      if len(mem) > 0 and mem.startswith(commandchar):

        # pull off the first token without the commandchar
        ses = mem.split(" ", 1)[0][1:]

        # is it a loop (aka repeating command)?
        if ses.isdigit():
          num = int(ses)
          if mem.find(" ") != -1:
            command = mem.split(" ", 1)[1]
            command = utils.strip_braces(command)
            if num > 0:
              for i in range(num):
                loopcommand = self.handleUserData(command, 1, session)
              historyitems.append(commandchar + ses + " {" + loopcommand + "}")
          continue

        # is it a session?
        if self._sessions.has_key(ses):
          input = mem.split(" ", 1)
          if len(input) < 2:
            self.set_current_session(self._sessions[ses])
          else:
            self.handleUserData(input[1], internal=1, session=self._sessions[ses])
          historyitems.append(mem)
          continue

        # is it "all" sessions?
        if ses == "all":
          newinput = mem.split(" ", 1)
          if len(newinput) > 1:
            newinput = newinput[1]
          else:
            newinput = commandchar + "cr"

          for sessionname in self._sessions.keys():
            if sessionname != "common":
              self._sessions[sessionname].handleUserData(newinput, internal)
          historyitems.append(mem)
          continue

      # if we get here then it is not a valid !-expression. and it's going 
      # to the default session
      historyitems.append(mem)

      # no command char, so we pass it on to the session.handleUserData
      # to do session oriented things
      session.handleUserData(mem, internal)

    # we don't record internal stuff or input that isn't supposed
    # to be echo'd
    executed = ";".join(historyitems)
    if internal == 0 and self.getConfigManager().get("mudecho") == 1:
      self.getManager("history").recordHistory(executed)

    return executed
Example #32
0
def main(defaultoptions={}):
    """
  This parses the command line arguments and makes sure they're all valid,
  instantiates a ui, does some setup, spins off an engine thread, and
  goes into the ui's mainloop.

  @param defaultoptions: the boot options to use.  we update the 
      config.options dict with these options--this is the easiest
      way to override the ui, moduledir, datadir, et al from a
      Lyntin run script.
  @type  defaultoptions: dict
  """
    try:
        import sys, os, traceback, ConfigParser
        from lyntin import config, event, utils, exported
        from lyntin.ui import base
        import locale

        locale.setlocale(locale.LC_ALL, '')

        config.options.update(defaultoptions)

        # read through options and arguments
        optlist = utils.parse_args(sys.argv[1:])

        for mem in optlist:
            if mem[0] == '--help':
                print constants.HELPTEXT
                sys.exit(0)

            elif mem[0] == '--version':
                print constants.VERSION
                sys.exit(0)

            elif mem[0] in ["--configuration", "-c"]:
                # ini files OVERRIDE the default options
                # they can provide multiple ini files, but each new
                # ini file will OVERRIDE the contents of the previous ini file
                # where the two files intersect.
                parser = ConfigParser.ConfigParser()
                parser.read([mem[1]])

                newoptions = {}
                for s in parser.sections():
                    for o in parser.options(s):
                        c = parser.get(s, o).split(",")
                        if newoptions.has_key(o):
                            newoptions[o] += c
                        else:
                            newoptions[o] = c

                config.options.update(newoptions)

            else:
                opt = mem[0]
                while opt.startswith("-"):
                    opt = opt[1:]

                if len(opt) > 0:
                    if config.options.has_key(opt):
                        if type(config.options[opt]) is list:
                            config.options[opt].append(mem[1])
                        else:
                            config.options[opt] = mem[1]
                    else:
                        config.options[opt] = [mem[1]]

        for mem in ["datadir", "ui", "commandchar"]:
            if config.options.has_key(mem) and type(
                    config.options[mem]) is list:
                config.options[mem] = config.options[mem][0]

        # if they haven't set the datadir via the command line, then
        # we go see if they have a HOME in their environment variables....
        if not config.options["datadir"]:
            if os.environ.has_key("HOME"):
                config.options["datadir"] = os.environ["HOME"]
        config.options["datadir"] = utils.fixdir(config.options["datadir"])

        def on_shutdown():
            """
      This gets called by the Python interpreter atexit.  The reason
      we do shutdown stuff here is we're more likely to catch things
      here than we are to let everything cycle through the 
      ShutdownEvent.  This should probably get fixed up at some point
      in the future.
      """
            sys.stderr.write("goodbye.\n")
            #exported.hook_spam("shutdown_hook", {})

        import atexit
        atexit.register(on_shutdown)

        # instantiate the engine
        Engine.instance = Engine()
        exported.myengine = Engine.instance
        Engine.instance._setupConfiguration()

        # instantiate the ui
        uiinstance = None
        try:
            uiname = str(config.options['ui'])
            modulename = uiname + "ui"
            uiinstance = base.get_ui(modulename)
            if not uiinstance:
                raise ValueError("No ui instance.")
        except Exception, e:
            print "Cannot start '%s': %s" % (uiname, e)
            traceback.print_exc()
            sys.exit(0)

        Engine.instance.setUI(uiinstance)

        # do some more silly initialization stuff
        # adds the .lyntinrc file to the readfile list if it exists.
        if config.options["datadir"]:
            lyntinrcfile = config.options["datadir"] + ".lyntinrc"
            if os.path.exists(lyntinrcfile):
                # we want the .lyntinrc file read in first, so then other
                # files can overwrite the contents therein
                config.options['readfile'].insert(0, lyntinrcfile)

        # import modules listed in modulesinit
        exported.write_message("Loading Lyntin modules.")

        try:
            import modules.__init__
            modules.__init__.load_modules()
        except:
            exported.write_traceback("Modules did not load correctly.")
            sys.exit(1)

        # spam the startup hook
        exported.hook_spam("startup_hook", {})

        commandchar = Engine.instance._managers["config"].get("commandchar")

        # handle command files
        for mem in config.options['readfile']:
            exported.write_message("Reading in file " + mem)
            # we have to escape windows os separators because \ has a specific
            # meaning in the argparser
            mem = mem.replace("\\", "\\\\")
            exported.lyntin_command("%sread %s" % (commandchar, mem),
                                    internal=1)

        # we're done initialization!
        exported.write_message(constants.STARTUPTEXT)
        Engine.instance.writePrompt()

        engine_thread = Engine.instance.startthread("engine",
                                                    Engine.instance.runengine)
        timer_thread = Engine.instance.startthread("timer",
                                                   Engine.instance.runtimer)
        try:
            Engine.instance._ui.runui()
        finally:
            sys.stderr.write("Shutting down...")
            event.ShutdownEvent().enqueue()
            engine_thread.join(10)
            timer_thread.join(10)
Example #33
0
    def handleUserData(self, input, internal=0, session=None):
        """
    This handles input lines from the user in a session-less context.
    The engine.handleUserData deals with global stuff and then
    passes the modified input to the session for session-oriented
    handling.  The session can call this method again with
    expanded input--this method is considered recursive.

    internal tells whether to spam the input hook and
    things of that nature.

    @param input: the data from the user
    @type  input: string

    @param internal: whether this should be executed internally or not.
        0 if we should spam the input hook and record
        the input to the historymanager; 1 if we shouldn't
    @type  internal: boolean

    @param session: the session scoping to execute this user input in
    @type  session: session.Session instance

    @return: the commands that were actually executed (may not be
        exactly what the user typed--this is for the history manager)
    @rtype: string
    """
        if self._managers["config"].get("debugmode") == 1:
            exported.write_message("evaluating: %s" % input)

        inputlist = utils.split_commands(
            self._managers["config"].get("splitchar"), input)
        if session == None:
            session = self._current_session

        historyitems = []
        commandchar = self._managers["config"].get("commandchar")
        for mem in inputlist:
            # mem = mem.strip()

            if len(mem) == 0:
                mem = commandchar + "cr"

            # if it's not internal we spam the hook with the raw input
            if internal == 0:
                exported.hook_spam("from_user_hook", {"data": mem})

            if mem.startswith("!"):
                memhistory = self.getManager("history").getHistoryItem(mem)
                if memhistory != None:
                    self.handleUserData(memhistory, 1, session)
                    historyitems.append(memhistory)
                    continue

            # if it starts with a # it's a loop, session or command
            if len(mem) > 0 and mem.startswith(commandchar):

                # pull off the first token without the commandchar
                ses = mem.split(" ", 1)[0][1:]

                # is it a loop (aka repeating command)?
                if ses.isdigit():
                    num = int(ses)
                    if mem.find(" ") != -1:
                        command = mem.split(" ", 1)[1]
                        command = utils.strip_braces(command)
                        if num > 0:
                            for i in range(num):
                                loopcommand = self.handleUserData(
                                    command, 1, session)
                            historyitems.append(commandchar + ses + " {" +
                                                loopcommand + "}")
                    continue

                # is it a session?
                if self._sessions.has_key(ses):
                    input = mem.split(" ", 1)
                    if len(input) < 2:
                        self.set_current_session(self._sessions[ses])
                    else:
                        self.handleUserData(input[1],
                                            internal=1,
                                            session=self._sessions[ses])
                    historyitems.append(mem)
                    continue

                # is it "all" sessions?
                if ses == "all":
                    newinput = mem.split(" ", 1)
                    if len(newinput) > 1:
                        newinput = newinput[1]
                    else:
                        newinput = commandchar + "cr"

                    for sessionname in self._sessions.keys():
                        if sessionname != "common":
                            self._sessions[sessionname].handleUserData(
                                newinput, internal)
                    historyitems.append(mem)
                    continue

            # if we get here then it is not a valid !-expression. and it's going
            # to the default session
            historyitems.append(mem)

            # no command char, so we pass it on to the session.handleUserData
            # to do session oriented things
            session.handleUserData(mem, internal)

        # we don't record internal stuff or input that isn't supposed
        # to be echo'd
        executed = ";".join(historyitems)
        if internal == 0 and self.getConfigManager().get("mudecho") == 1:
            self.getManager("history").recordHistory(executed)

        return executed
Example #34
0
 def execute(self):
   """ Execute."""
   exported.hook_spam(*(self._vargs), **(self._nargs))
Example #35
0
 def execute(self):
   """ Execute the shutdown."""
   exported.hook_spam("shutdown_hook", {})
Example #36
0
  def handleNego(self, data):
    """
    Removes telnet negotiation stuff from the stream and handles it.

    @param data: the incoming data from the mud that we need to parse
        for telnet control code stuff
    @type  data: string

    @return: the data without the telnet control codes
    @rtype:  string
    """
    marker = -1
    i = data.find(IAC)

    while (i != -1):
      if i + 1 >= len(data):
        marker = i
        break

      if data[i+1] == NOP:
        data = data[:i] + data[i+2:]
        self.logControl("receive: IAC NOP")

      elif data[i+1] == GA or data[i+1] == TELOPT_EOR:
        data = data[:i] + data[i+2:]
        # if data is a prompt delimited with some telnet option,
        # then we'll mark the server as "server with good prompting"
        self._good_prompts = 1

      elif data[i+1] == IAC:
        data = data[:i] + data[i+1:]
        i = i + 1
        self.logControl("receive: IAC IAC")

      else:
        if i + 2 >= len(data):
          marker = i
          break

        # handles DO/DONT/WILL/WONT stuff
        if data[i+1] in DDWW:
          option = data[i:i+3]

          self.logControl("receive: " + _cc(option))
          if option[2] == ECHO:
            if option[1] == WILL:
              self._config.change("mudecho", "off")
            elif option[1] == WONT:
              self._config.change("mudecho", "on")

          elif option[2] == TERMTYPE:
            if option[1] == DO:
              self.write(IAC + WILL + TERMTYPE, 0)
              self.logControl("send: IAC WILL TERMTYPE")
            else:
              self.write(IAC + WONT + TERMTYPE, 0)
              self.logControl("send: IAC WONT TERMTYPE")

          elif option[2] == EOR:
            if option[1] == WILL:
              self.write(IAC + DO + EOR, 0)
              self.logControl("send: IAC DO EOR")

          else:
            args = {"session": self._session, "data": option}
            # this will give us back the args (in the case that no one
            # handled it) or None (in the case that someone handled it
            # and raised a StopSpammingException).
            ret = exported.hook_spam("net_handle_telnet_option", args)

            if ret:
              if option[1] in DD:
                self.write(IAC + WONT + option[2], 0)
                self.logControl("send: " + _cc(IAC + WONT + option[2]))

              elif option[1] in WW:
                self.write(IAC + DONT + option[2], 0)
                self.logControl("send: " + _cc(IAC + DONT + option[2]))

          data = data[:i] + data[i+3:]

        # handles SB...SE stuff
        elif data[i+1] == SB:

          end = data.find(SE, i)
          if end == -1:
            marker = i
            break

          option = data[i:end+1]
          self.logControl("receive: " + _cc(option))

          if option[2] == TERMTYPE and option[3] == SEND:
            self.write(IAC + SB + TERMTYPE + IS + self._termtype + IAC + SE, 0)
            self.logControl("send: IAC SB TERMTYPE IS " + self._termtype + " IAC SE")
          else:
            args = {"session": self._session, "data": option}
            # this will give us back the args (in the case that no one
            # handled it) or None (in the case that someone handled it
            # and raised a StopSpammingException).
            ret = exported.hook_spam("net_handle_telnet_option", args)

          data = data[:i] + data[end+1:]

        # in case they passed us something weird we remove the IAC and
        # move on
        else:
          data = data[:i] + data[i+1:]

      i = data.find(IAC, i)

    if marker != -1:
      self._nego_buffer = data[marker:]
      data = data[:marker]

    return data
Example #37
0
 def execute(self):
   """ Execute."""
   exported.hook_spam("from_mud_hook", {"session": self._session, "data": self._input})
   exported.myengine.handleMudData(self._session, self._input)