sqlmap/lib/core/subprocessng.py

203 lines
5.5 KiB
Python
Raw Permalink Normal View History

2019-05-08 13:47:52 +03:00
#!/usr/bin/env python
"""
2022-01-03 13:30:34 +03:00
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
2017-10-11 15:50:46 +03:00
See the file 'LICENSE' for copying permission
"""
2019-06-04 13:15:39 +03:00
from __future__ import division
import errno
import os
import subprocess
import time
2019-05-03 16:33:32 +03:00
from lib.core.compat import buffer
2019-08-27 14:39:18 +03:00
from lib.core.convert import getBytes
from lib.core.settings import IS_WIN
if IS_WIN:
try:
from win32file import ReadFile, WriteFile
from win32pipe import PeekNamedPipe
except ImportError:
pass
import msvcrt
else:
import select
import fcntl
def blockingReadFromFD(fd):
# Quick twist around original Twisted function
# Blocking read from a non-blocking file descriptor
2019-05-03 16:33:32 +03:00
output = b""
while True:
try:
output += os.read(fd, 8192)
except (OSError, IOError) as ioe:
if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
# Uncomment the following line if the process seems to
# take a huge amount of cpu time
# time.sleep(0.01)
2013-01-04 02:57:07 +04:00
continue
else:
raise
break
if not output:
2013-01-10 18:02:28 +04:00
raise EOFError("fd %s has been closed." % fd)
return output
def blockingWriteToFD(fd, data):
# Another quick twist
while True:
try:
data_length = len(data)
2011-04-30 17:20:05 +04:00
wrote_data = os.write(fd, data)
except (OSError, IOError) as io:
if io.errno in (errno.EAGAIN, errno.EINTR):
2013-01-04 02:57:07 +04:00
continue
else:
2013-01-04 02:57:07 +04:00
raise
if wrote_data < data_length:
blockingWriteToFD(fd, data[wrote_data:])
break
# the following code is taken from http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/
class Popen(subprocess.Popen):
def recv(self, maxsize=None):
return self._recv('stdout', maxsize)
def recv_err(self, maxsize=None):
return self._recv('stderr', maxsize)
def send_recv(self, input='', maxsize=None):
return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
def get_conn_maxsize(self, which, maxsize):
if maxsize is None:
maxsize = 1024
elif maxsize < 1:
maxsize = 1
return getattr(self, which), maxsize
def _close(self, which):
getattr(self, which).close()
setattr(self, which, None)
2019-03-27 17:48:51 +03:00
if IS_WIN:
def send(self, input):
if not self.stdin:
return None
try:
x = msvcrt.get_osfhandle(self.stdin.fileno())
2019-05-29 17:42:04 +03:00
(_, written) = WriteFile(x, input)
except ValueError:
return self._close('stdin')
2021-09-16 14:59:42 +03:00
except Exception as ex:
if getattr(ex, "args", None) and ex.args[0] in (109, errno.ESHUTDOWN):
return self._close('stdin')
raise
2010-10-29 14:51:09 +04:00
return written
def _recv(self, which, maxsize):
conn, maxsize = self.get_conn_maxsize(which, maxsize)
if conn is None:
return None
try:
x = msvcrt.get_osfhandle(conn.fileno())
2019-05-29 17:42:04 +03:00
(read, nAvail, _) = PeekNamedPipe(x, 0)
if maxsize < nAvail:
nAvail = maxsize
if nAvail > 0:
2019-05-29 17:42:04 +03:00
(_, read) = ReadFile(x, nAvail, None)
2013-12-28 16:47:40 +04:00
except (ValueError, NameError):
return self._close(which)
2021-09-16 14:59:42 +03:00
except Exception as ex:
if getattr(ex, "args", None) and ex.args[0] in (109, errno.ESHUTDOWN):
return self._close(which)
raise
2010-10-29 14:51:09 +04:00
if self.universal_newlines:
read = self._translate_newlines(read)
return read
else:
def send(self, input):
if not self.stdin:
return None
if not select.select([], [self.stdin], [], 0)[1]:
return 0
try:
written = os.write(self.stdin.fileno(), input)
except OSError as ex:
2019-06-04 13:15:39 +03:00
if ex.args[0] == errno.EPIPE: # broken pipe
return self._close('stdin')
raise
2010-10-29 14:51:09 +04:00
return written
def _recv(self, which, maxsize):
conn, maxsize = self.get_conn_maxsize(which, maxsize)
if conn is None:
return None
flags = fcntl.fcntl(conn, fcntl.F_GETFL)
if not conn.closed:
2013-01-10 16:18:44 +04:00
fcntl.fcntl(conn, fcntl.F_SETFL, flags | os.O_NONBLOCK)
try:
if not select.select([conn], [], [], 0)[0]:
return ''
r = conn.read(maxsize)
if not r:
return self._close(which)
if self.universal_newlines:
r = self._translate_newlines(r)
return r
finally:
if not conn.closed:
fcntl.fcntl(conn, fcntl.F_SETFL, flags)
def recv_some(p, t=.1, e=1, tr=5, stderr=0):
if tr < 1:
tr = 1
2013-01-10 16:18:44 +04:00
x = time.time() + t
y = []
r = ''
if stderr:
pr = p.recv_err
else:
pr = p.recv
while time.time() < x or r:
r = pr()
if r is None:
2010-10-29 14:51:09 +04:00
break
elif r:
y.append(r)
else:
2013-01-10 16:18:44 +04:00
time.sleep(max((x - time.time()) / tr, 0))
2019-05-03 16:33:32 +03:00
return b''.join(y)
def send_all(p, data):
if not data:
return
2019-08-27 14:39:18 +03:00
data = getBytes(data)
while len(data):
sent = p.send(data)
if not isinstance(sent, int):
break
2019-05-03 16:33:32 +03:00
data = buffer(data[sent:])