115 lines
3.3 KiB
Python
115 lines
3.3 KiB
Python
# Copyright (c) Twisted Matrix Laboratories.
|
|
# See LICENSE for details.
|
|
|
|
|
|
"""Telnet-based shell."""
|
|
|
|
# twisted imports
|
|
from twisted.protocols import telnet
|
|
from twisted.internet import protocol
|
|
from twisted.python import log, failure
|
|
|
|
# system imports
|
|
import string, copy, sys
|
|
|
|
|
|
class Shell(telnet.Telnet):
|
|
"""A Python command-line shell."""
|
|
|
|
def connectionMade(self):
|
|
telnet.Telnet.connectionMade(self)
|
|
self.lineBuffer = []
|
|
|
|
def loggedIn(self):
|
|
self.transport.write(">>> ")
|
|
|
|
def checkUserAndPass(self, username, password):
|
|
return ((self.factory.username == username) and (password == self.factory.password))
|
|
|
|
def write(self, data):
|
|
"""Write some data to the transport.
|
|
"""
|
|
self.transport.write(data)
|
|
|
|
def telnet_Command(self, cmd):
|
|
if self.lineBuffer:
|
|
if not cmd:
|
|
cmd = string.join(self.lineBuffer, '\n') + '\n\n\n'
|
|
self.doCommand(cmd)
|
|
self.lineBuffer = []
|
|
return "Command"
|
|
else:
|
|
self.lineBuffer.append(cmd)
|
|
self.transport.write("... ")
|
|
return "Command"
|
|
else:
|
|
self.doCommand(cmd)
|
|
return "Command"
|
|
|
|
def doCommand(self, cmd):
|
|
|
|
# TODO -- refactor this, Reality.author.Author, and the manhole shell
|
|
#to use common functionality (perhaps a twisted.python.code module?)
|
|
fn = '$telnet$'
|
|
result = None
|
|
try:
|
|
out = sys.stdout
|
|
sys.stdout = self
|
|
try:
|
|
code = compile(cmd,fn,'eval')
|
|
result = eval(code, self.factory.namespace)
|
|
except:
|
|
try:
|
|
code = compile(cmd, fn, 'exec')
|
|
exec code in self.factory.namespace
|
|
except SyntaxError, e:
|
|
if not self.lineBuffer and str(e)[:14] == "unexpected EOF":
|
|
self.lineBuffer.append(cmd)
|
|
self.transport.write("... ")
|
|
return
|
|
else:
|
|
failure.Failure().printTraceback(file=self)
|
|
log.deferr()
|
|
self.write('\r\n>>> ')
|
|
return
|
|
except:
|
|
failure.Failure().printTraceback(file=self)
|
|
log.deferr()
|
|
self.write('\r\n>>> ')
|
|
return
|
|
finally:
|
|
sys.stdout = out
|
|
|
|
self.factory.namespace['_'] = result
|
|
if result is not None:
|
|
self.transport.write(repr(result))
|
|
self.transport.write('\r\n')
|
|
self.transport.write(">>> ")
|
|
|
|
|
|
|
|
class ShellFactory(protocol.Factory):
|
|
username = "admin"
|
|
password = "admin"
|
|
protocol = Shell
|
|
service = None
|
|
|
|
def __init__(self):
|
|
self.namespace = {
|
|
'factory': self,
|
|
'service': None,
|
|
'_': None
|
|
}
|
|
|
|
def setService(self, service):
|
|
self.namespace['service'] = self.service = service
|
|
|
|
def __getstate__(self):
|
|
"""This returns the persistent state of this shell factory.
|
|
"""
|
|
dict = self.__dict__
|
|
ns = copy.copy(dict['namespace'])
|
|
dict['namespace'] = ns
|
|
if ns.has_key('__builtins__'):
|
|
del ns['__builtins__']
|
|
return dict
|