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