def watch(self,ip,*args): proc = PtyProcess.spawn('cccaster.v3.0.exe -n -s %s' % ip) self.aproc = proc curCon = "" lastCon = "" con = "" logger.write('\n== Watch %s ==\n' % ip) while proc.isalive(): curCon = ansi_escape.sub('',str(proc.read())) con += lastCon + curCon if "fast-forward)" in con: logger.write('\n=================================\n') logger.write(str(con.split())) proc.write('1') #start spectating, find names after r = [] for x in reversed(con.split()): if x == '*' and len(r) > 0: if r[0] == "Spectating": break elif x != '*' and x.replace('*','') != '': r.insert(0,x) CApp.DirectScreen.activePop.modalTxt.text = ' '.join(r) #replace connecting text with match name in caster break else: if lastCon != curCon: lastCon = curCon continue
def replays(self): proc = PtyProcess.spawn('cccaster.v3.0.exe') self.aproc = proc while proc.isalive(): if "Offline" in proc.read(): proc.write('4') time.sleep(0.1) proc.write('5') break
def training(self): proc = PtyProcess.spawn('cccaster.v3.0.exe') self.aproc = proc while proc.isalive(): if "Offline" in proc.read(): proc.write('4') #4 is offline time.sleep(0.1) proc.write('1') break
def pty(self, command='cmd', cwd=None, textmode='ansi', width=80): """ Setup a virtual terminal. Stdout of the executing process live printed. textmode = 'ansi' or 'raw' """ from winpty import PtyProcess #install pywinpty #The orginal terminal is killed or hidden? #logging.root.handlers[0] becomes invalid? if isinstance(logging.root.handlers[0], logging.StreamHandler): logging.root.handlers.pop(0) #WINPTY_SHOW_CONSOLE to 1 os.environ['WINPTY_SHOW_CONSOLE'] = '1' #proc = PtyProcess.spawn(command, cwd=cwd) proc = PtyProcess.spawn(command, dimensions=(24, width)) # def output_reader(proc): #PTYESC = '\033]' #while proc.isalive(): # text = proc.readline() # if text == '': raise EOFError('End of File') # sys.stdout._write_mode(text, textmode) def output_reader(proc): """Read one line from the pseudoterminal as bytes. Can block if there is nothing to read. Raises :exc:`EOFError` if the terminal was closed. """ buf = [] while True: try: ch = proc.read(1) except EOFError: sys.stdout._write_mode(''.join(buf)+'\n', textmode) sys.stdout._write_mode('End of Process\n', textmode) return buf.append(ch) if ch == '\n': sys.stdout._write_mode(''.join(buf), textmode) buf.clear() stdout_thread = threading.Thread(target=output_reader, args=(proc,)) stdout_thread.start() sys.stdout.copy_to_thread(stdout_thread.ident) while proc.isalive(): try: cmd = input('', timeout=1) proc.write(cmd + '\r\n') except queue.Empty: pass
def __init__(self, command: List[str], on_output: Optional[Callable[[str], None]], on_close: Optional[Callable[[], None]] = None, cwd=None) -> None: print('Starting process: {}'.format(command)) self.process = PtyProcess.spawn(command, cwd=cwd) self.pid = self.process.pid self.on_close = on_close self.closed = False if on_output: thread = threading.Thread(target=self._read, args=(on_output,)) thread.start()
def host(self,sc): #sc is active screen to trigger frame delay select proc = PtyProcess.spawn('cccaster.v3.0.exe -n 0') self.aproc = proc logger.write('\n== Host ==\n') while proc.isalive(): ip = re.findall(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{,5}',proc.read()) #find IP and port combo for host if ip != []: self.adr = str(ip[0]) break logger.write('IP: %s\n' % self.adr) curCon = "" lastCon = "" con = "" while proc.isalive(): curCon = ansi_escape.sub('',str(proc.read())) con += lastCon + curCon if self.playing == False and self.rs == -1 and self.ds == -1: n = self.isValidRead(con) if n != False: logger.write('\n=================================\n') logger.write(str(con.split())) self.ds = int(n[-2]) - int(n[-1]) self.rs = int(n[-1]) r = [] namecheck = False #try to read names from caster output for x in reversed(con.split()): if namecheck == False and x == "connected": namecheck = True elif namecheck == True and x == '*': break elif namecheck == True and x.replace('*','') != '': r.insert(0,x) p = re.findall('\d+\.\d+',con) #find all floats in caster output and use the last one [-1] to make sure we get caster text sc.frameset(' '.join(r),n[-2],p[-1]) while True: #todo optimize frameset stutter by making this a thread if self.rf != -1 and self.df != -1: proc.write('\x08') #two backspace keys for edge case of >9 frames proc.write('\x08') proc.write(str(self.rf)) proc.write('\x0D') time.sleep(0.1) #slight delay to let caster refresh screen proc.write('\x08') proc.write('\x08') proc.write(str(self.df)) proc.write('\x0D') self.playing = True #set netplaying to avoid more reads break else: if lastCon != curCon: lastCon = curCon continue
def join(self,ip,sc,*args): proc = PtyProcess.spawn('cccaster.v3.0.exe -n %s' % ip) self.aproc = proc curCon = "" lastCon = "" con = "" logger.write('\n== Join %s ==\n' % ip) while proc.isalive(): curCon = ansi_escape.sub('',str(proc.read())) con += lastCon + curCon if self.playing == False and self.rs == -1 and self.ds == -1: n = self.isValidRead(con) if n != False: logger.write('\n=================================\n') logger.write(str(con.split())) self.ds = int(n[-2]) - int(n[-1]) self.rs = int(n[-1]) r = [] namecheck = False #try to read names from caster output for x in con.split(): if x == "to" and namecheck == False: namecheck = True elif x == '*' and namecheck == True: break elif namecheck == True and x.replace('*','') != '': r.append(x) p = re.findall('\d+\.\d+',con) #find all floats in caster output and use the last one [-1] to make sure we get caster text sc.frameset(' '.join(r),n[-2],p[-1]) while True: if self.rf != -1 and self.df != -1: proc.write('\x08') proc.write('\x08') proc.write(str(self.rf)) proc.write('\x0D') time.sleep(0.1) proc.write('\x08') proc.write('\x08') proc.write(str(self.df)) proc.write('\x0D') self.playing = True break else: if lastCon != curCon: lastCon = curCon continue
def start_pty(shell="powershell.exe", lines=30, columns=120): logger.notice("Starting %s (%d/%d)", shell, lines, columns) try: # Import of winpty may sometimes fail because of problems with the needed dll. # Therefore we do not import at toplevel from winpty import PtyProcess # pylint: disable=import-error,import-outside-toplevel except ImportError as err: logger.error("Failed to start pty: %s", err, exc_info=True) raise process = PtyProcess.spawn(shell, dimensions=(lines, columns)) def read(length: int): return process.read(length).encode("utf-8") def write(data: bytes): return process.write(data.decode("utf-8")) def stop(): process.close() return (read, write, stop)
def read_and_forward_pty_output(sid, data): max_read_bytes = 1024 * 20 import time if _platform == 'win32': os.environ['PYWINPTY_BACKEND'] = '1' process = PtyProcess.spawn('cmd.exe') process.write(r'"{0}" "{1}" 2>>&1'.format(connection_data[0], connection_data[1])) process.write("\r\n") app.config['sessions'][request.sid] = process pdata[request.sid] = process set_term_size(process, 50, 50) while True: read_stdout(process, sid, max_read_bytes, win_emit_output=True) else: p, parent, fd = create_pty_terminal(connection_data) while p and p.poll() is None: if request.sid in app.config['sessions']: # This code is added to make this unit testable. if "is_test" not in data: sio.sleep(0.01) else: data['count'] += 1 if data['count'] == 5: break timeout = 0 # module provides access to platform-specific I/O # monitoring functions (data_ready, _, _) = select.select([parent, fd], [], [], timeout) read_terminal_data(parent, data_ready, max_read_bytes, sid)
def spawn(argv, win_repeat_argv0=False, **kwargs): # TODO: For whatever reason, Docker needs their name as padding in the arguments again. if win_repeat_argv0: argv = [argv[0]] + argv term_size = os.get_terminal_size() process = PtyProcess.spawn(argv, dimensions=(term_size[1], term_size[0] - 2)) # TODO: Is this even thread-safe? # TODO: "pressing up" (...in bash doesn't do what it's supposed to) def read(): try: while True: if msvcrt.kbhit(): process.write(msvcrt.getwch()) except EOFError: pass ## WRITE t = Thread(target=read) t.daemon = True # thread dies with the program t.start() ## READ try: while True: # Remove some unprintable escape sequences when using winpty # TODO: FAR from perfect yet (what if sequence is on "boundary"?). # Source: https://stackoverflow.com/a/14693789 ansi_escape = re.compile(r'\x1B\[\?25[hl]*[ -/]*[@-~]') # TODO: Little bit of a buffering issue here. sys.stdout.write(ansi_escape.sub('', process.read(4096))) except EOFError: pass process.close() return process.exitstatus()
def _spawn(self, argv, cwd=None, env=None): from winpty import PtyProcess return PtyProcess.spawn(argv, cwd, env)
def test_import(self): from winpty import PtyProcess self.assertTrue("winpty" in sys.modules) proc = PtyProcess.spawn('cmd.exe') self.assertTrue(proc.isalive()) proc.terminate(True)