Commit ddf1f0dc authored by Denis Bilenko's avatar Denis Bilenko

simpler implementation of backdoor.py

parent d175d984
# @author Bob Ippolito # Copyright (c) 2009-2014, gevent contributors
# # Based on eventlet.backdoor Copyright (c) 2005-2006, Bob Ippolito
# Copyright (c) 2005-2006, Bob Ippolito
# Copyright (c) 2007, Linden Research, Inc.
# Copyright (c) 2008, Donovan Preston
# Copyright (c) 2009-2010, Denis Bilenko
# Copyright (c) 2011, gevent contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import print_function from __future__ import print_function
import sys import sys
...@@ -30,7 +7,7 @@ from code import InteractiveConsole ...@@ -30,7 +7,7 @@ from code import InteractiveConsole
from gevent import socket from gevent import socket
from gevent.greenlet import Greenlet from gevent.greenlet import Greenlet
from gevent.hub import PY3 from gevent.hub import PY3, getcurrent
from gevent.server import StreamServer from gevent.server import StreamServer
__all__ = ['BackdoorServer'] __all__ = ['BackdoorServer']
...@@ -45,58 +22,61 @@ except AttributeError: ...@@ -45,58 +22,61 @@ except AttributeError:
sys.ps2 = '... ' sys.ps2 = '... '
class SocketConsole(Greenlet): class _Greenlet_stdreplace(Greenlet):
_fileobj = None
def __init__(self, locals, conn, banner=None):
Greenlet.__init__(self)
self.locals = locals
self.desc = _fileobject(conn)
self.banner = banner
def finalize(self):
self.desc = None
def switch(self, *args, **kw): def switch(self, *args, **kw):
self.saved = sys.stdin, sys.stderr, sys.stdout if self._fileobj is not None:
sys.stdin = sys.stdout = sys.stderr = self.desc self.switch_in()
Greenlet.switch(self, *args, **kw) Greenlet.switch(self, *args, **kw)
def switch_in(self):
self.saved = sys.stdin, sys.stderr, sys.stdout
sys.stdin = sys.stdout = sys.stderr = self._fileobj
def switch_out(self): def switch_out(self):
sys.stdin, sys.stderr, sys.stdout = self.saved sys.stdin, sys.stderr, sys.stdout = self.saved
self.saved = None
def _run(self): def run(self):
try: try:
try: return Greenlet.run(self)
console = InteractiveConsole(self.locals)
# __builtins__ may either be the __builtin__ module or
# __builtin__.__dict__ in the latter case typing
# locals() at the backdoor prompt spews out lots of
# useless stuff
try:
import __builtin__
console.locals["__builtins__"] = __builtin__
except ImportError:
import builtins
console.locals["builtins"] = builtins
console.interact(banner=self.banner)
except SystemExit: # raised by quit()
if not PY3:
sys.exc_clear()
finally: finally:
# XXX why is this necessary?
self.switch_out() self.switch_out()
self.finalize()
class BackdoorServer(StreamServer): class BackdoorServer(StreamServer):
def __init__(self, listener, locals=None, banner=None, **server_args): def __init__(self, listener, locals=None, banner=None, **server_args):
StreamServer.__init__(self, listener, spawn=None, **server_args) StreamServer.__init__(self, listener, spawn=_Greenlet_stdreplace.spawn, **server_args)
self.locals = locals self.locals = locals
self.banner = banner self.banner = banner
# QQQ passing pool instance as 'spawn' is not possible; should it be fixed? self.stderr = sys.stderr
def handle(self, conn, address): def handle(self, conn, address):
SocketConsole.spawn(self.locals, conn, banner=self.banner) f = getcurrent()._fileobj = _fileobject(conn)
f.stderr = self.stderr
getcurrent().switch_in()
try:
console = InteractiveConsole(self.locals)
# __builtins__ may either be the __builtin__ module or
# __builtin__.__dict__ in the latter case typing
# locals() at the backdoor prompt spews out lots of
# useless stuff
try:
import __builtin__
console.locals["__builtins__"] = __builtin__
except ImportError:
import builtins
console.locals["builtins"] = builtins
console.interact(banner=self.banner)
except SystemExit: # raised by quit()
if not PY3:
sys.exc_clear()
finally:
conn.close()
f.close()
class _fileobject(socket._fileobject): class _fileobject(socket._fileobject):
...@@ -118,4 +98,4 @@ if __name__ == '__main__': ...@@ -118,4 +98,4 @@ if __name__ == '__main__':
if not sys.argv[1:]: if not sys.argv[1:]:
print('USAGE: %s PORT' % sys.argv[0]) print('USAGE: %s PORT' % sys.argv[0])
else: else:
BackdoorServer(('127.0.0.1', int(sys.argv[1]))).serve_forever() BackdoorServer(('127.0.0.1', int(sys.argv[1])), locals={'hello': 'world'}).serve_forever()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment