def start_proc(self): preexec = noop stdin = stdout = stderr = None cqlshlog.info("Spawning %r subprocess with args: %r and env: %r" % (self.exe_path, self.args, self.env)) if self.realtty: masterfd, slavefd = pty.openpty() preexec = (lambda: set_controlling_pty(masterfd, slavefd)) self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args), env=self.env, preexec_fn=preexec, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=False) os.close(slavefd) self.childpty = masterfd self.send = self.send_tty self.read = self.read_tty else: stdin = stdout = subprocess.PIPE stderr = subprocess.STDOUT self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args), env=self.env, stdin=stdin, stdout=stdout, stderr=stderr, bufsize=0, close_fds=False) self.send = self.send_pipe if self.tty: self.winpty = WinPty(self.proc.stdout) self.read = self.read_winpty else: self.read = self.read_pipe
class ProcRunner: def __init__(self, path, tty=True, env=None, args=()): self.exe_path = path self.args = args self.tty = bool(tty) self.realtty = self.tty and not is_win() if env is None: env = {} self.env = env self.readbuf = '' self.start_proc() def start_proc(self): preexec = noop stdin = stdout = stderr = None cqlshlog.info("Spawning %r subprocess with args: %r and env: %r" % (self.exe_path, self.args, self.env)) if self.realtty: masterfd, slavefd = pty.openpty() preexec = (lambda: set_controlling_pty(masterfd, slavefd)) self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args), env=self.env, preexec_fn=preexec, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=False) os.close(slavefd) self.childpty = masterfd self.send = self.send_tty self.read = self.read_tty else: stdin = stdout = subprocess.PIPE stderr = subprocess.STDOUT self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args), env=self.env, stdin=stdin, stdout=stdout, stderr=stderr, bufsize=0, close_fds=False) self.send = self.send_pipe if self.tty: self.winpty = WinPty(self.proc.stdout) self.read = self.read_winpty else: self.read = self.read_pipe def close(self): cqlshlog.info("Closing %r subprocess." % (self.exe_path,)) if self.realtty: os.close(self.childpty) else: self.proc.stdin.close() cqlshlog.debug("Waiting for exit") return self.proc.wait() def send_tty(self, data): os.write(self.childpty, data) def send_pipe(self, data): self.proc.stdin.write(data) def read_tty(self, blksize, timeout=None): return os.read(self.childpty, blksize) def read_pipe(self, blksize, timeout=None): return self.proc.stdout.read(blksize) def read_winpty(self, blksize, timeout=None): return self.winpty.read(blksize, timeout) def read_until(self, until, blksize=4096, timeout=None, flags=0, ptty_timeout=None): if not isinstance(until, re._pattern_type): until = re.compile(until, flags) cqlshlog.debug("Searching for %r" % (until.pattern,)) got = self.readbuf self.readbuf = '' with timing_out(timeout): while True: val = self.read(blksize, ptty_timeout) cqlshlog.debug("read %r from subproc" % (val,)) if val == '': raise EOFError("'until' pattern %r not found" % (until.pattern,)) got += val m = until.search(got) if m is not None: self.readbuf = got[m.end():] got = got[:m.end()] return got def read_lines(self, numlines, blksize=4096, timeout=None): lines = [] with timing_out(timeout): for n in range(numlines): lines.append(self.read_until('\n', blksize=blksize)) return lines def read_up_to_timeout(self, timeout, blksize=4096): got = self.readbuf self.readbuf = '' curtime = time() stoptime = curtime + timeout while curtime < stoptime: try: with timing_out(stoptime - curtime): stuff = self.read(blksize) except TimeoutError: break cqlshlog.debug("read %r from subproc" % (stuff,)) if stuff == '': break got += stuff curtime = time() return got