#!/usr/bin/env python # ~/clickclack.py -s -r <(echo 'CAPAB START 1206\r\nSERVER test.1459.io dummy 1S2 :moo.\r\nBURST %s\r\nENDBURST\r\n' socat stdio openssl:127.0.0.1:6005,cert=1S1.cert,key=1S1.key,snihost=chaos.1459.io,commonname=chaos.1459.io CLIENT_MODE = True DEBUG = False CONN_SEND = b'' import select, subprocess, sys, os, tty, termios, time def parse_irc_line(line): source = b'' cmd = b'' _trailing = None args = [] if line[0:1] == b':': source_pieces = line.split(None, 1) source = source_pieces[0][1:] line = source_pieces[1] if b' :' in line: trailing_pieces = line.split(b' :', 1) _trailing = trailing_pieces[1] line = trailing_pieces[0] cmd, *args = line.split() if _trailing is not None: args.append(_trailing) return (source, cmd, args) def format_irc_args(args): if b' ' in args[-1]: args[-1] = b':' + args[-1] return b' '.join(args) if __name__ == '__main__': argv = sys.argv[1:] while len(argv) and len(argv[0]) and argv[0][0] == '-': opt = argv[0][1:] del argv[0] if opt == 's': CLIENT_MODE = False elif opt == 'r': CONN_SEND = argv[0] del argv[0] elif opt == '-': break else: #h print(f'Usage: {sys.argv[0]} [-h|-s|-r "send on connect file"|--] [socat command...]', file=sys.stderr) sys.exit() proc = subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) conn_send_cmds = open(CONN_SEND, 'rb').read() conn_send_cmds = conn_send_cmds.replace(b'%s', bytes(str(time.time()).encode('ascii'))) proc.stdin.write(conn_send_cmds) proc.stdin.flush() os.set_blocking(proc.stdout.fileno(), False) os.set_blocking(proc.stderr.fileno(), False) child_buffer = bytearray() while True: if DEBUG: print('selecting') rd = select.select([proc.stdout, proc.stderr, sys.stdin.buffer], [], [])[0] for f in rd: if DEBUG: print(f'reading {f!r}') if f is proc.stdout: if DEBUG: print(f'writing to stdout') child_buffer += f.read() child_buffer.replace(b'\r',b'') if b'\n' in child_buffer: lines = child_buffer.split(b'\n') for line in lines[:-1]: if line == b'': continue source, cmd, args = parse_irc_line(line) sys.stdout.buffer.write(line+b'\r\n') sys.stdout.buffer.flush() if cmd == b'PING': if CLIENT_MODE: pong = b'PONG %s\r\n' % (format_irc_args(args)) else: pong = b'PONG %s\r\n' % (source) sys.stdout.buffer.write(pong) sys.stdout.buffer.flush() proc.stdin.write(pong) proc.stdin.flush() child_buffer = lines[-1] if f is proc.stderr: if DEBUG: print(f'writing to stderr') sys.stderr.buffer.write(f.read()) sys.stderr.buffer.flush() if f is sys.stdin.buffer: if DEBUG: print(f'writing to child') proc.stdin.write(f.readline()) proc.stdin.flush()