pipetool.py revision 59a7b9f69b5b745e58c01288cb4f85fb535250b0
153e354dd0edd0d111fb7512f366c4764ffc2e681Phil#! /usr/bin/env python 253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 353e354dd0edd0d111fb7512f366c4764ffc2e681Phil## This file is part of Scapy 453e354dd0edd0d111fb7512f366c4764ffc2e681Phil## See http://www.secdev.org/projects/scapy for more informations 553e354dd0edd0d111fb7512f366c4764ffc2e681Phil## Copyright (C) Philippe Biondi <phil@secdev.org> 653e354dd0edd0d111fb7512f366c4764ffc2e681Phil## This program is published under a GPLv2 license 753e354dd0edd0d111fb7512f366c4764ffc2e681Phil 859a7b9f69b5b745e58c01288cb4f85fb535250b0gpotterimport os 953e354dd0edd0d111fb7512f366c4764ffc2e681Philimport subprocess 1053e354dd0edd0d111fb7512f366c4764ffc2e681Philimport itertools 1153e354dd0edd0d111fb7512f366c4764ffc2e681Philimport collections 1253e354dd0edd0d111fb7512f366c4764ffc2e681Philimport time 1353e354dd0edd0d111fb7512f366c4764ffc2e681Philimport Queue 1459a7b9f69b5b745e58c01288cb4f85fb535250b0gpotterfrom threading import Lock, Thread 156057906368d55634d11e1d19a5cca1f127595b11Robin Jarry 16c8aedce97942cf1963c137902d50d14cd5c28bf0gpotterfrom scapy.automaton import Message, select_objects 17c8aedce97942cf1963c137902d50d14cd5c28bf0gpotterfrom scapy.consts import WINDOWS 182a54fe68cadcb2b75c9c31244499c2b21f385eb4gpotterfrom scapy.error import log_interactive, warning 196057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.config import conf 20c8aedce97942cf1963c137902d50d14cd5c28bf0gpotterfrom scapy.utils import get_temp_file, do_graph 21c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter 22c8aedce97942cf1963c137902d50d14cd5c28bf0gpotterimport scapy.arch 2353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 2453e354dd0edd0d111fb7512f366c4764ffc2e681Philclass PipeEngine: 2553e354dd0edd0d111fb7512f366c4764ffc2e681Phil pipes = {} 2653e354dd0edd0d111fb7512f366c4764ffc2e681Phil @classmethod 2753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def list_pipes(cls): 2853e354dd0edd0d111fb7512f366c4764ffc2e681Phil for pn,pc in sorted(cls.pipes.items()): 2953e354dd0edd0d111fb7512f366c4764ffc2e681Phil doc = pc.__doc__ or "" 3053e354dd0edd0d111fb7512f366c4764ffc2e681Phil if doc: 3153e354dd0edd0d111fb7512f366c4764ffc2e681Phil doc = doc.splitlines()[0] 3253e354dd0edd0d111fb7512f366c4764ffc2e681Phil print "%20s: %s" % (pn, doc) 3353e354dd0edd0d111fb7512f366c4764ffc2e681Phil @classmethod 3453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def list_pipes_detailed(cls): 3553e354dd0edd0d111fb7512f366c4764ffc2e681Phil for pn,pc in sorted(cls.pipes.items()): 3653e354dd0edd0d111fb7512f366c4764ffc2e681Phil if pc.__doc__: 3753e354dd0edd0d111fb7512f366c4764ffc2e681Phil print "###### %s\n %s" % (pn ,pc.__doc__) 3853e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 3953e354dd0edd0d111fb7512f366c4764ffc2e681Phil print "###### %s" % pn 4053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 4153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, *pipes): 4253e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_pipes = set() 4353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_sources = set() 4453e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_drains = set() 4553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_sinks = set() 4653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._add_pipes(*pipes) 4759a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter self.thread_lock = Lock() 4859a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter self.command_lock = Lock() 49c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__fd_queue = [] 5053e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.__fdr,self.__fdw = os.pipe() 5153e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.threadid = None 5253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __getattr__(self, attr): 5353e354dd0edd0d111fb7512f366c4764ffc2e681Phil if attr.startswith("spawn_"): 5453e354dd0edd0d111fb7512f366c4764ffc2e681Phil dname = attr[6:] 5553e354dd0edd0d111fb7512f366c4764ffc2e681Phil if dname in self.pipes: 5653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def f(*args, **kargs): 5753e354dd0edd0d111fb7512f366c4764ffc2e681Phil k = self.pipes[dname] 5853e354dd0edd0d111fb7512f366c4764ffc2e681Phil p = k(*args, **kargs) 5953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.add(p) 6053e354dd0edd0d111fb7512f366c4764ffc2e681Phil return p 6153e354dd0edd0d111fb7512f366c4764ffc2e681Phil return f 6253e354dd0edd0d111fb7512f366c4764ffc2e681Phil raise AttributeError(attr) 6353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 64c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter def checkRecv(self): 65c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter return len(self.__fd_queue) > 0 66c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter 67c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter def fileno(self): 68c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter return self.__fdr 69c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter 70c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter def _read_cmd(self): 71c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__fd_queue.pop() 72c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter return os.read(self.__fdr,1) 73c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter 74c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter def _write_cmd(self, _cmd): 75c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter os.write(self.__fdw, _cmd) 76c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__fd_queue.append("X") 77c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter 7853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def add_one_pipe(self, pipe): 7953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_pipes.add(pipe) 8053e354dd0edd0d111fb7512f366c4764ffc2e681Phil if isinstance(pipe, Source): 8153e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_sources.add(pipe) 8253e354dd0edd0d111fb7512f366c4764ffc2e681Phil if isinstance(pipe, Drain): 8353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_drains.add(pipe) 8453e354dd0edd0d111fb7512f366c4764ffc2e681Phil if isinstance(pipe, Sink): 8553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.active_sinks.add(pipe) 8653e354dd0edd0d111fb7512f366c4764ffc2e681Phil 8753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def get_pipe_list(self, pipe): 8853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def flatten(p, l): 8953e354dd0edd0d111fb7512f366c4764ffc2e681Phil l.add(p) 9053e354dd0edd0d111fb7512f366c4764ffc2e681Phil for q in p.sources|p.sinks|p.high_sources|p.high_sinks: 9153e354dd0edd0d111fb7512f366c4764ffc2e681Phil if q not in l: 9253e354dd0edd0d111fb7512f366c4764ffc2e681Phil flatten(q, l) 93c277f8948afe9d19703168fca385d2fa6df67657Phil pl = set() 9453e354dd0edd0d111fb7512f366c4764ffc2e681Phil flatten(pipe, pl) 9553e354dd0edd0d111fb7512f366c4764ffc2e681Phil return pl 9653e354dd0edd0d111fb7512f366c4764ffc2e681Phil 9753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _add_pipes(self, *pipes): 98c277f8948afe9d19703168fca385d2fa6df67657Phil pl = set() 9953e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in pipes: 100c277f8948afe9d19703168fca385d2fa6df67657Phil pl |= self.get_pipe_list(p) 101c277f8948afe9d19703168fca385d2fa6df67657Phil pl -= self.active_pipes 102c277f8948afe9d19703168fca385d2fa6df67657Phil for q in pl: 103c277f8948afe9d19703168fca385d2fa6df67657Phil self.add_one_pipe(q) 104c277f8948afe9d19703168fca385d2fa6df67657Phil return pl 10553e354dd0edd0d111fb7512f366c4764ffc2e681Phil 10653e354dd0edd0d111fb7512f366c4764ffc2e681Phil 10753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def run(self): 10853e354dd0edd0d111fb7512f366c4764ffc2e681Phil log_interactive.info("Pipe engine thread started.") 10953e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 11053e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in self.active_pipes: 11153e354dd0edd0d111fb7512f366c4764ffc2e681Phil p.start() 11253e354dd0edd0d111fb7512f366c4764ffc2e681Phil sources = self.active_sources 113c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter sources.add(self) 11453e354dd0edd0d111fb7512f366c4764ffc2e681Phil exhausted = set([]) 11553e354dd0edd0d111fb7512f366c4764ffc2e681Phil RUN=True 11653e354dd0edd0d111fb7512f366c4764ffc2e681Phil STOP_IF_EXHAUSTED = False 11753e354dd0edd0d111fb7512f366c4764ffc2e681Phil while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1): 118c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter fds = select_objects(sources, 2, customTypes=(AutoSource, PipeEngine)) 11953e354dd0edd0d111fb7512f366c4764ffc2e681Phil for fd in fds: 120c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if fd is self: 121c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd = self._read_cmd() 12253e354dd0edd0d111fb7512f366c4764ffc2e681Phil if cmd == "X": 12353e354dd0edd0d111fb7512f366c4764ffc2e681Phil RUN=False 12453e354dd0edd0d111fb7512f366c4764ffc2e681Phil break 12553e354dd0edd0d111fb7512f366c4764ffc2e681Phil elif cmd == "B": 12653e354dd0edd0d111fb7512f366c4764ffc2e681Phil STOP_IF_EXHAUSTED = True 12753e354dd0edd0d111fb7512f366c4764ffc2e681Phil elif cmd == "A": 12853e354dd0edd0d111fb7512f366c4764ffc2e681Phil sources = self.active_sources-exhausted 12953e354dd0edd0d111fb7512f366c4764ffc2e681Phil sources.add(self.__fdr) 13053e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 13153e354dd0edd0d111fb7512f366c4764ffc2e681Phil warning("Unknown internal pipe engine command: %r. Ignoring." % cmd) 13253e354dd0edd0d111fb7512f366c4764ffc2e681Phil elif fd in sources: 13353e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 13453e354dd0edd0d111fb7512f366c4764ffc2e681Phil fd.deliver() 13553e354dd0edd0d111fb7512f366c4764ffc2e681Phil except Exception,e: 13653e354dd0edd0d111fb7512f366c4764ffc2e681Phil log_interactive.exception("piping from %s failed: %s" % (fd.name, e)) 13753e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 13853e354dd0edd0d111fb7512f366c4764ffc2e681Phil if fd.exhausted(): 13953e354dd0edd0d111fb7512f366c4764ffc2e681Phil exhausted.add(fd) 14053e354dd0edd0d111fb7512f366c4764ffc2e681Phil sources.remove(fd) 14153e354dd0edd0d111fb7512f366c4764ffc2e681Phil except KeyboardInterrupt: 14253e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 14353e354dd0edd0d111fb7512f366c4764ffc2e681Phil finally: 14453e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 14553e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in self.active_pipes: 14653e354dd0edd0d111fb7512f366c4764ffc2e681Phil p.stop() 14753e354dd0edd0d111fb7512f366c4764ffc2e681Phil finally: 14853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.thread_lock.release() 14953e354dd0edd0d111fb7512f366c4764ffc2e681Phil log_interactive.info("Pipe engine thread stopped.") 15053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 15153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 15253e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.thread_lock.acquire(0): 15359a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter _t = Thread(target=self.run) 15459a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter _t.start() 15559a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter self.threadid = _t.ident 15653e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 15753e354dd0edd0d111fb7512f366c4764ffc2e681Phil warning("Pipe engine already running") 15853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def wait_and_stop(self): 15953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.stop(_cmd="B") 16053e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self, _cmd="X"): 16153e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 16253e354dd0edd0d111fb7512f366c4764ffc2e681Phil with self.command_lock: 16353e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.threadid is not None: 164c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self._write_cmd(_cmd) 16553e354dd0edd0d111fb7512f366c4764ffc2e681Phil while not self.thread_lock.acquire(0): 16653e354dd0edd0d111fb7512f366c4764ffc2e681Phil time.sleep(0.01) # interruptible wait for thread to terminate 16753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.thread_lock.release() # (not using .join() because it needs 'threading' module) 16853e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 16953e354dd0edd0d111fb7512f366c4764ffc2e681Phil warning("Pipe engine thread not running") 17053e354dd0edd0d111fb7512f366c4764ffc2e681Phil except KeyboardInterrupt: 17153e354dd0edd0d111fb7512f366c4764ffc2e681Phil print "Interrupted by user." 17253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 17353e354dd0edd0d111fb7512f366c4764ffc2e681Phil def add(self, *pipes): 174c277f8948afe9d19703168fca385d2fa6df67657Phil pipes = self._add_pipes(*pipes) 17553e354dd0edd0d111fb7512f366c4764ffc2e681Phil with self.command_lock: 17653e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.threadid is not None: 17753e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in pipes: 17853e354dd0edd0d111fb7512f366c4764ffc2e681Phil p.start() 179c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self._write_cmd("A") 18053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 18153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def graph(self,**kargs): 18253e354dd0edd0d111fb7512f366c4764ffc2e681Phil g=['digraph "pipe" {',"\tnode [shape=rectangle];",] 18353e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in self.active_pipes: 18453e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append('\t"%i" [label="%s"];' % (id(p), p.name)) 18553e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append("") 18653e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append("\tedge [color=blue, arrowhead=vee];") 18753e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in self.active_pipes: 18853e354dd0edd0d111fb7512f366c4764ffc2e681Phil for q in p.sinks: 18953e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append('\t"%i" -> "%i";' % (id(p), id(q))) 19053e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append("") 191dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil g.append("\tedge [color=purple, arrowhead=veevee];") 19253e354dd0edd0d111fb7512f366c4764ffc2e681Phil for p in self.active_pipes: 19353e354dd0edd0d111fb7512f366c4764ffc2e681Phil for q in p.high_sinks: 194dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil g.append('\t"%i" -> "%i";' % (id(p), id(q))) 195dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil g.append("") 196dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil g.append("\tedge [color=red, arrowhead=diamond];") 197dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil for p in self.active_pipes: 198dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil for q in p.trigger_sinks: 199dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil g.append('\t"%i" -> "%i";' % (id(p), id(q))) 20053e354dd0edd0d111fb7512f366c4764ffc2e681Phil g.append('}') 20153e354dd0edd0d111fb7512f366c4764ffc2e681Phil graph = "\n".join(g) 202c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter do_graph(graph, **kargs) 20353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 20453e354dd0edd0d111fb7512f366c4764ffc2e681Phil 20553e354dd0edd0d111fb7512f366c4764ffc2e681Philclass _ConnectorLogic(object): 20653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self): 20753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.sources = set() 20853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.sinks = set() 20953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.high_sources = set() 21053e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.high_sinks = set() 211dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil self.trigger_sources = set() 212dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil self.trigger_sinks = set() 21353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 21453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __lt__(self, other): 21553e354dd0edd0d111fb7512f366c4764ffc2e681Phil other.sinks.add(self) 21653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.sources.add(other) 21753e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 21853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __gt__(self, other): 21953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.sinks.add(other) 22053e354dd0edd0d111fb7512f366c4764ffc2e681Phil other.sources.add(self) 22153e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 22253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __eq__(self, other): 22353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self > other 22453e354dd0edd0d111fb7512f366c4764ffc2e681Phil other > self 22553e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 22653e354dd0edd0d111fb7512f366c4764ffc2e681Phil 22753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __lshift__(self, other): 22853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.high_sources.add(other) 22953e354dd0edd0d111fb7512f366c4764ffc2e681Phil other.high_sinks.add(self) 23053e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 23153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __rshift__(self, other): 23253e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.high_sinks.add(other) 23353e354dd0edd0d111fb7512f366c4764ffc2e681Phil other.high_sources.add(self) 23453e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 23553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __floordiv__(self, other): 23653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self >> other 23753e354dd0edd0d111fb7512f366c4764ffc2e681Phil other >> self 23853e354dd0edd0d111fb7512f366c4764ffc2e681Phil return other 23953e354dd0edd0d111fb7512f366c4764ffc2e681Phil 240dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil def __xor__(self, other): 241dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil self.trigger_sinks.add(other) 242dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil other.trigger_sources.add(self) 243dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil return other 24453e354dd0edd0d111fb7512f366c4764ffc2e681Phil 24553e354dd0edd0d111fb7512f366c4764ffc2e681Philclass Pipe(_ConnectorLogic): 24653e354dd0edd0d111fb7512f366c4764ffc2e681Phil class __metaclass__(type): 24753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __new__(cls, name, bases, dct): 24853e354dd0edd0d111fb7512f366c4764ffc2e681Phil c = type.__new__(cls, name, bases, dct) 24953e354dd0edd0d111fb7512f366c4764ffc2e681Phil PipeEngine.pipes[name] = c 25053e354dd0edd0d111fb7512f366c4764ffc2e681Phil return c 25153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None): 25253e354dd0edd0d111fb7512f366c4764ffc2e681Phil _ConnectorLogic.__init__(self) 25353e354dd0edd0d111fb7512f366c4764ffc2e681Phil if name is None: 25453e354dd0edd0d111fb7512f366c4764ffc2e681Phil name = "%s" % (self.__class__.__name__) 25553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.name = name 25653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _send(self, msg): 25753e354dd0edd0d111fb7512f366c4764ffc2e681Phil for s in self.sinks: 25853e354dd0edd0d111fb7512f366c4764ffc2e681Phil s.push(msg) 25953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _high_send(self, msg): 26053e354dd0edd0d111fb7512f366c4764ffc2e681Phil for s in self.high_sinks: 26153e354dd0edd0d111fb7512f366c4764ffc2e681Phil s.high_push(msg) 262f1288d41516059cab24e840f0d8cd2d1bf7735e0phil def _trigger(self, msg=None): 263dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil for s in self.trigger_sinks: 264dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s.on_trigger(msg) 26553e354dd0edd0d111fb7512f366c4764ffc2e681Phil 26653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __repr__(self): 26753e354dd0edd0d111fb7512f366c4764ffc2e681Phil ct = conf.color_theme 26853e354dd0edd0d111fb7512f366c4764ffc2e681Phil s = "%s%s" % (ct.punct("<"), ct.layer_name(self.name)) 26953e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.sources or self.sinks: 27053e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+= " %s" % ct.punct("[") 27153e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.sources: 27253e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+="%s%s" % (ct.punct(",").join(ct.field_name(s.name) for s in self.sources), 27353e354dd0edd0d111fb7512f366c4764ffc2e681Phil ct.field_value(">")) 27453e354dd0edd0d111fb7512f366c4764ffc2e681Phil s += ct.layer_name("#") 27553e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.sinks: 27653e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+="%s%s" % (ct.field_value(">"), 27753e354dd0edd0d111fb7512f366c4764ffc2e681Phil ct.punct(",").join(ct.field_name(s.name) for s in self.sinks)) 27853e354dd0edd0d111fb7512f366c4764ffc2e681Phil s += ct.punct("]") 27953e354dd0edd0d111fb7512f366c4764ffc2e681Phil 28053e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.high_sources or self.high_sinks: 28153e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+= " %s" % ct.punct("[") 28253e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.high_sources: 28353e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+="%s%s" % (ct.punct(",").join(ct.field_name(s.name) for s in self.high_sources), 28453e354dd0edd0d111fb7512f366c4764ffc2e681Phil ct.field_value(">>")) 28553e354dd0edd0d111fb7512f366c4764ffc2e681Phil s += ct.layer_name("#") 28653e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.high_sinks: 28753e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+="%s%s" % (ct.field_value(">>"), 28853e354dd0edd0d111fb7512f366c4764ffc2e681Phil ct.punct(",").join(ct.field_name(s.name) for s in self.high_sinks)) 28953e354dd0edd0d111fb7512f366c4764ffc2e681Phil s += ct.punct("]") 29053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 291dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil if self.trigger_sources or self.trigger_sinks: 292dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s+= " %s" % ct.punct("[") 293dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil if self.trigger_sources: 294dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s+="%s%s" % (ct.punct(",").join(ct.field_name(s.name) for s in self.trigger_sources), 295dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil ct.field_value("^")) 296dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s += ct.layer_name("#") 297dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil if self.trigger_sinks: 298dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s+="%s%s" % (ct.field_value("^"), 299dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil ct.punct(",").join(ct.field_name(s.name) for s in self.trigger_sinks)) 300dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil s += ct.punct("]") 301dbabf910cf2ddd7e420190267dd0c2a7abc2dfb1phil 30253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 30353e354dd0edd0d111fb7512f366c4764ffc2e681Phil s += ct.punct(">") 30453e354dd0edd0d111fb7512f366c4764ffc2e681Phil return s 30553e354dd0edd0d111fb7512f366c4764ffc2e681Phil 30653e354dd0edd0d111fb7512f366c4764ffc2e681Philclass Source(Pipe): 30753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None): 30853e354dd0edd0d111fb7512f366c4764ffc2e681Phil Pipe.__init__(self, name=name) 30953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.is_exhausted = False 31053e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _read_message(self): 31153e354dd0edd0d111fb7512f366c4764ffc2e681Phil return Message() 31253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def deliver(self): 31353e354dd0edd0d111fb7512f366c4764ffc2e681Phil msg = self._read_message 31453e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._send(msg) 31553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def fileno(self): 31653e354dd0edd0d111fb7512f366c4764ffc2e681Phil return None 31753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def exhausted(self): 31853e354dd0edd0d111fb7512f366c4764ffc2e681Phil return self.is_exhausted 31953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 32053e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 32153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self): 32253e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 32353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 32453e354dd0edd0d111fb7512f366c4764ffc2e681Philclass Drain(Pipe): 32553e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Repeat messages from low/high entries to (resp.) low/high exits 32653e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 32753e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|-------|->> 32853e354dd0edd0d111fb7512f366c4764ffc2e681Phil | | 32953e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|-------|-> 33053e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 33153e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 33253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 33353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._send(msg) 33453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 33553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._high_send(msg) 33653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 33753e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 33853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self): 33953e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 34053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 34153e354dd0edd0d111fb7512f366c4764ffc2e681Philclass Sink(Pipe): 34253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 34353e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 34453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 34553e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 34653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 34753e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 34853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self): 34953e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 35053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 35153e354dd0edd0d111fb7512f366c4764ffc2e681Phil 35253e354dd0edd0d111fb7512f366c4764ffc2e681Philclass AutoSource(Source): 35353e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None): 35453e354dd0edd0d111fb7512f366c4764ffc2e681Phil Source.__init__(self, name=name) 35553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.__fdr,self.__fdw = os.pipe() 35653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._queue = collections.deque() 35753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def fileno(self): 35853e354dd0edd0d111fb7512f366c4764ffc2e681Phil return self.__fdr 359c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter def checkRecv(self): 360c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter return len(self._queue) > 0 36153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _gen_data(self, msg): 36253e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._queue.append((msg,False)) 36353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._wake_up() 36453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _gen_high_data(self, msg): 36553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._queue.append((msg,True)) 36653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._wake_up() 36753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _wake_up(self): 36853e354dd0edd0d111fb7512f366c4764ffc2e681Phil os.write(self.__fdw,"x") 36953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def deliver(self): 37053e354dd0edd0d111fb7512f366c4764ffc2e681Phil os.read(self.__fdr,1) 37153e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 37253e354dd0edd0d111fb7512f366c4764ffc2e681Phil msg,high = self._queue.popleft() 37353e354dd0edd0d111fb7512f366c4764ffc2e681Phil except IndexError: #empty queue. Exhausted source 37453e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 37553e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 37653e354dd0edd0d111fb7512f366c4764ffc2e681Phil if high: 37753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._high_send(msg) 37853e354dd0edd0d111fb7512f366c4764ffc2e681Phil else: 37953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._send(msg) 38053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 38153e354dd0edd0d111fb7512f366c4764ffc2e681Philclass ThreadGenSource(AutoSource): 38253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None): 38353e354dd0edd0d111fb7512f366c4764ffc2e681Phil AutoSource.__init__(self, name=name) 38453e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.RUN = False 38553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def generate(self): 38653e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 38753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 38853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.RUN = True 38959a7b9f69b5b745e58c01288cb4f85fb535250b0gpotter Thread(target=self.generate).start() 39053e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self): 39153e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.RUN = False 39253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 39353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 39453e354dd0edd0d111fb7512f366c4764ffc2e681Phil 39553e354dd0edd0d111fb7512f366c4764ffc2e681Philclass ConsoleSink(Sink): 39653e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Print messages on low and high entries 39753e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 39853e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--. |->> 39953e354dd0edd0d111fb7512f366c4764ffc2e681Phil | print | 40053e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--' |-> 40153e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 40253e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 40353e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 40453e354dd0edd0d111fb7512f366c4764ffc2e681Phil print ">%r" % msg 40553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 40653e354dd0edd0d111fb7512f366c4764ffc2e681Phil print ">>%r" % msg 40753e354dd0edd0d111fb7512f366c4764ffc2e681Phil 40853e354dd0edd0d111fb7512f366c4764ffc2e681Philclass RawConsoleSink(Sink): 40953e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Print messages on low and high entries 41053e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 41153e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--. |->> 41253e354dd0edd0d111fb7512f366c4764ffc2e681Phil | write | 41353e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--' |-> 41453e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 41553e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 41653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None, newlines=True): 41753e354dd0edd0d111fb7512f366c4764ffc2e681Phil Sink.__init__(self, name=name) 41853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.newlines = newlines 41953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 42053e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.newlines: 42153e354dd0edd0d111fb7512f366c4764ffc2e681Phil msg += "\n" 42253e354dd0edd0d111fb7512f366c4764ffc2e681Phil os.write(1, str(msg)) 42353e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 42453e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.newlines: 42553e354dd0edd0d111fb7512f366c4764ffc2e681Phil msg += "\n" 42653e354dd0edd0d111fb7512f366c4764ffc2e681Phil os.write(1, str(msg)) 42753e354dd0edd0d111fb7512f366c4764ffc2e681Phil 42853e354dd0edd0d111fb7512f366c4764ffc2e681Philclass CLIFeeder(AutoSource): 42953e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Send messages from python command line 43053e354dd0edd0d111fb7512f366c4764ffc2e681Phil +--------+ 43153e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-| |->> 43253e354dd0edd0d111fb7512f366c4764ffc2e681Phil | send() | 43353e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-| `----|-> 43453e354dd0edd0d111fb7512f366c4764ffc2e681Phil +--------+ 43553e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 43653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def send(self, msg): 43753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._gen_data(msg) 43853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def close(self): 43953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.is_exhausted = True 44053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 44153e354dd0edd0d111fb7512f366c4764ffc2e681Philclass CLIHighFeeder(CLIFeeder): 44253e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Send messages from python command line to high output 44353e354dd0edd0d111fb7512f366c4764ffc2e681Phil +--------+ 44453e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-| .----|->> 44553e354dd0edd0d111fb7512f366c4764ffc2e681Phil | send() | 44653e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-| |-> 44753e354dd0edd0d111fb7512f366c4764ffc2e681Phil +--------+ 44853e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 44953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def send(self, msg): 45053e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._gen_high_data(msg) 45153e354dd0edd0d111fb7512f366c4764ffc2e681Phil 45253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 45353e354dd0edd0d111fb7512f366c4764ffc2e681Philclass PeriodicSource(ThreadGenSource): 45453e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Generage messages periodically on low exit 45553e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 45653e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-| |->> 45753e354dd0edd0d111fb7512f366c4764ffc2e681Phil | msg,T | 45853e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-| `----|-> 45953e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 46053e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 46153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, msg, period, period2=0, name=None): 46253e354dd0edd0d111fb7512f366c4764ffc2e681Phil ThreadGenSource.__init__(self,name=name) 46353e354dd0edd0d111fb7512f366c4764ffc2e681Phil if not hasattr(msg, "__iter__"): 46453e354dd0edd0d111fb7512f366c4764ffc2e681Phil msg=[msg] 46553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.msg = msg 46653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.period = period 46753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.period2 = period2 46853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def generate(self): 46953e354dd0edd0d111fb7512f366c4764ffc2e681Phil while self.RUN: 47053e354dd0edd0d111fb7512f366c4764ffc2e681Phil empty_gen = True 47153e354dd0edd0d111fb7512f366c4764ffc2e681Phil for m in self.msg: 47253e354dd0edd0d111fb7512f366c4764ffc2e681Phil empty_gen = False 47353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._gen_data(m) 47453e354dd0edd0d111fb7512f366c4764ffc2e681Phil time.sleep(self.period) 47553e354dd0edd0d111fb7512f366c4764ffc2e681Phil if empty_gen: 47653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.is_exhausted = True 47753e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._wake_up() 47853e354dd0edd0d111fb7512f366c4764ffc2e681Phil time.sleep(self.period2) 47953e354dd0edd0d111fb7512f366c4764ffc2e681Phil 48053e354dd0edd0d111fb7512f366c4764ffc2e681Philclass TermSink(Sink): 48153e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Print messages on low and high entries on a separate terminal 48253e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 48353e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--. |->> 48453e354dd0edd0d111fb7512f366c4764ffc2e681Phil | print | 48553e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--' |-> 48653e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 48753e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 48853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None, keepterm=True, newlines=True, openearly=True): 48953e354dd0edd0d111fb7512f366c4764ffc2e681Phil Sink.__init__(self, name=name) 49053e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.keepterm = keepterm 49153e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.newlines = newlines 49253e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.openearly = openearly 49353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.opened = False 49453e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.openearly: 49553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.start() 49653e354dd0edd0d111fb7512f366c4764ffc2e681Phil 49753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def start(self): 49853e354dd0edd0d111fb7512f366c4764ffc2e681Phil if not self.opened: 49953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.opened = True 500c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if WINDOWS: 501c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__f = get_temp_file() 502c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.name = "Scapy" if self.name is None else self.name 503c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter # Start a powershell in a new window and print the PID 504c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd = "$app = Start-Process PowerShell -ArgumentList '-command &{$host.ui.RawUI.WindowTitle=\\\"%s\\\";Get-Content \\\"%s\\\" -wait}' -passthru; echo $app.Id" % (self.name, self.__f.replace("\\", "\\\\")) 505c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter print([conf.prog.powershell, cmd]) 506c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter _p = subprocess.Popen([conf.prog.powershell, cmd], stdout=subprocess.PIPE) 507c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter _output, _stderr = _p.communicate() 508c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter # This is the process PID 509c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__p = int(_output) 510c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter print("PID:" + str(self.__p)) 511c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter else: 512c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__r,self.__w = os.pipe() 513c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd = ["xterm"] 514c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if self.name is not None: 515c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd.extend(["-title",self.name]) 516c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if self.keepterm: 517c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd.append("-hold") 518c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter cmd.extend(["-e", "cat 0<&%i" % self.__r]) 519c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__p = subprocess.Popen(cmd, shell=True, executable="/bin/bash") 520c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter os.close(self.__r) 52153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def stop(self): 52253e354dd0edd0d111fb7512f366c4764ffc2e681Phil if not self.keepterm: 52353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.opened = False 524c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if not WINDOWS: 525c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter os.close(self.__w) 526c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__p.kill() 527c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__p.wait() 528c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter else: 529c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter # Recipe to kill process with PID 530c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter # http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/ 531c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter import ctypes 532c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter PROCESS_TERMINATE = 1 533c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.__p) 534c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter ctypes.windll.kernel32.TerminateProcess(handle, -1) 535c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter ctypes.windll.kernel32.CloseHandle(handle) 53653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def _print(self, s): 53753e354dd0edd0d111fb7512f366c4764ffc2e681Phil if self.newlines: 53853e354dd0edd0d111fb7512f366c4764ffc2e681Phil s+="\n" 539c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter if WINDOWS: 540c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__w = open(self.__f, "a") 541c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__w.write(s) 542c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter self.__w.close() 543c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter else: 544c8aedce97942cf1963c137902d50d14cd5c28bf0gpotter os.write(self.__w, s) 54553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 54653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._print(str(msg)) 54753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 54853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._print(str(msg)) 54953e354dd0edd0d111fb7512f366c4764ffc2e681Phil 55053e354dd0edd0d111fb7512f366c4764ffc2e681Phil 55153e354dd0edd0d111fb7512f366c4764ffc2e681Philclass QueueSink(Sink): 55253e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Collect messages from high and low entries and queue them. Messages are unqueued with the .recv() method. 55353e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 55453e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--. |->> 55553e354dd0edd0d111fb7512f366c4764ffc2e681Phil | queue | 55653e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--' |-> 55753e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 55853e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 55953e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, name=None): 56053e354dd0edd0d111fb7512f366c4764ffc2e681Phil Sink.__init__(self, name=name) 56153e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.q = Queue.Queue() 56253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 56353e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.q.put(msg) 56453e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 56553e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.q.put(msg) 56653e354dd0edd0d111fb7512f366c4764ffc2e681Phil def recv(self): 56753e354dd0edd0d111fb7512f366c4764ffc2e681Phil while True: 56853e354dd0edd0d111fb7512f366c4764ffc2e681Phil try: 56953e354dd0edd0d111fb7512f366c4764ffc2e681Phil return self.q.get(True, timeout=0.1) 57053e354dd0edd0d111fb7512f366c4764ffc2e681Phil except Queue.Empty: 57153e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 57253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 57353e354dd0edd0d111fb7512f366c4764ffc2e681Phil 57453e354dd0edd0d111fb7512f366c4764ffc2e681Philclass TransformDrain(Drain): 57553e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Apply a function to messages on low and high entry 57653e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 57753e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--[f]--|->> 57853e354dd0edd0d111fb7512f366c4764ffc2e681Phil | | 57953e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--[f]--|-> 58053e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 58153e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 58253e354dd0edd0d111fb7512f366c4764ffc2e681Phil def __init__(self, f, name=None): 58353e354dd0edd0d111fb7512f366c4764ffc2e681Phil Drain.__init__(self, name=name) 58453e354dd0edd0d111fb7512f366c4764ffc2e681Phil self.f = f 58553e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 58653e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._send(self.f(msg)) 58753e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 58853e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._high_send(self.f(msg)) 58953e354dd0edd0d111fb7512f366c4764ffc2e681Phil 59053e354dd0edd0d111fb7512f366c4764ffc2e681Philclass UpDrain(Drain): 59153e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Repeat messages from low entry to high exit 59253e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 59353e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-| ,--|->> 59453e354dd0edd0d111fb7512f366c4764ffc2e681Phil | / | 59553e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-|--' |-> 59653e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 59753e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 59853e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 59953e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._high_send(msg) 60053e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 60153e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 60253e354dd0edd0d111fb7512f366c4764ffc2e681Phil 60353e354dd0edd0d111fb7512f366c4764ffc2e681Philclass DownDrain(Drain): 60453e354dd0edd0d111fb7512f366c4764ffc2e681Phil """Repeat messages from high entry to low exit 60553e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 60653e354dd0edd0d111fb7512f366c4764ffc2e681Phil >>-|--. |->> 60753e354dd0edd0d111fb7512f366c4764ffc2e681Phil | \ | 60853e354dd0edd0d111fb7512f366c4764ffc2e681Phil >-| `--|-> 60953e354dd0edd0d111fb7512f366c4764ffc2e681Phil +-------+ 61053e354dd0edd0d111fb7512f366c4764ffc2e681Phil""" 61153e354dd0edd0d111fb7512f366c4764ffc2e681Phil def push(self, msg): 61253e354dd0edd0d111fb7512f366c4764ffc2e681Phil pass 61353e354dd0edd0d111fb7512f366c4764ffc2e681Phil def high_push(self, msg): 61453e354dd0edd0d111fb7512f366c4764ffc2e681Phil self._send(msg) 615