diff options
author | Malfurious <m@lfurio.us> | 2022-03-14 00:17:08 -0400 |
---|---|---|
committer | Malfurious <m@lfurio.us> | 2022-03-14 00:17:08 -0400 |
commit | 6e24dc3d70b9e915c89d47dc8d7c816f1ba8ffab (patch) | |
tree | 3495e18ec3171d3155c9f0a3430ea2b869243a03 | |
parent | 13ad3d5d41fec4042a35424e0b21c0f8136ed690 (diff) | |
parent | 38a8b3f528d9e02fd08d7d98a5c4beb530700cc2 (diff) | |
download | lib-des-gnux-6e24dc3d70b9e915c89d47dc8d7c816f1ba8ffab.tar.gz lib-des-gnux-6e24dc3d70b9e915c89d47dc8d7c816f1ba8ffab.zip |
Merge branch 'sploit/repl-qol'
This branch addresses some user experience issues when attempting to use
Sploit interactively, in the Python REPL (or iPython).
In particular:
- Target output is more responsive
- Setting up io plumbing is simplified
* sploit/repl-qol:
sploit: Clean up function Comm.interact()
sploit: Add function popen()
sploit: Add Comm property 'readonwrite'
sploit: Add function Comm.readall_nonblock()
-rw-r--r-- | tools/sploit/sploit/comm.py | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/tools/sploit/sploit/comm.py b/tools/sploit/sploit/comm.py index 604045c..265ab96 100644 --- a/tools/sploit/sploit/comm.py +++ b/tools/sploit/sploit/comm.py @@ -11,6 +11,8 @@ class Comm: logonread = True logonwrite = False flushonwrite = True + readonwrite = False + timeout = 0.25 # seconds def __init__(self, backend): self.back = backend @@ -42,6 +44,16 @@ class Comm: pass return data + def readall_nonblock(self): + try: + os.set_blocking(self.back.stdin.fileno(), False) + poll = select.poll() + poll.register(self.back.stdin, select.POLLIN) + poll.poll(self.timeout) + return self.readall() + finally: + os.set_blocking(self.back.stdin.fileno(), True) + def readuntil(self, pred, /, *args, **kwargs): data = b'' pred = bind(pred, *args, **kwargs) @@ -70,46 +82,47 @@ class Comm: self.back.stdout.write(data) if self.flushonwrite : self.back.stdout.flush() if self.logonwrite : ilog(data, file=sys.stdout, color=ALT) + if self.readonwrite : self.readall_nonblock() def writeline(self, data): self.write(data + b'\n') def interact(self): - ilog("<--Interact Mode-->") stdin = sys.stdin.buffer - os.set_blocking(self.back.stdin.fileno(), False) - os.set_blocking(stdin.fileno(), False) - poll = select.poll() - poll.register(self.back.stdin, select.POLLIN) - poll.register(stdin, select.POLLIN) - brk = False - def readall(read, write): - while(True): - data = read() - if(data == b''): - break - write(data) - def writeinput(write): - ilog(write, file=sys.stdout, color=NORMAL) + event = select.POLLIN + + def readall_stdin(): + for line in stdin: + self.write(line) + readtable = { - stdin.fileno() : lambda : readall(stdin.readline, self.write), - self.back.stdin.fileno() : lambda : readall(self.back.stdin.readline, writeinput) + self.back.stdin.fileno(): self.readall_nonblock, + stdin.fileno(): readall_stdin, } - readtable[self.back.stdin.fileno()]() - while(not brk): - try: - ioevents = poll.poll(100) - for ev in ioevents: - if(ev[1] & select.POLLIN): - readtable[ev[0]]() - else: - brk = True - break - except KeyboardInterrupt: - break - os.set_blocking(self.back.stdin.fileno(), True) - os.set_blocking(stdin.fileno(), True) - ilog("<--Interact Mode Done-->") + + try: + ilog("<--Interact Mode-->") + os.set_blocking(stdin.fileno(), False) + + poll = select.poll() + poll.register(self.back.stdin, event) + poll.register(stdin, event) + + while True: + for fd, e in poll.poll(self.timeout): + if not e & event: return + readtable[fd]() + except KeyboardInterrupt: + pass + finally: + os.set_blocking(stdin.fileno(), True) + ilog("<--Interact Mode Done-->") + +def popen(cmdline=''): + io = Comm((Process(cmdline.split()) if len(cmdline) > 0 else Pipes())) + io.readall_nonblock() + io.readonwrite = True + return io class Process: def __init__(self, args): |