Skip to content

Instantly share code, notes, and snippets.

@andyneff
Last active July 18, 2024 22:29
Show Gist options
  • Save andyneff/9602acf55b6671a0ce706dc471385cff to your computer and use it in GitHub Desktop.
Save andyneff/9602acf55b6671a0ce706dc471385cff to your computer and use it in GitHub Desktop.
Python script to emulate socat behavior, but uses a single executable instead of one per connection
#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE
from socket import *
import atexit
from select import select
from logging import getLogger, basicConfig
logger = getLogger(__name__)
def cleanup():
try:
os.remove(sys.argv[1])
except:
pass
atexit.register(cleanup)
def main():
# This works really well, because ssh reads from tty, not stdin. If this
# doesn't work for you, see SSH_ASKPASS
pid = Popen(sys.argv[2:], stdin=PIPE, stdout=PIPE)
socket_name = sys.argv[1]
s = socket(AF_UNIX, SOCK_STREAM)
s.bind(socket_name)
s.listen(1)
while True:
logger.info('waiting to connect')
conn, addr = s.accept()
logger.info('connected')
try:
while True:
reads, _, _ = select([pid.stdout, conn], [], [], 1)
# data (cmd) from socket
if conn in reads:
data = conn.recv(1024*64)
if data:
pid.stdin.write(data)
if data.endswith(b'\r\n'):
pid.stdin.flush()
# logger.debug('IN:{}'.format(data))
else:
logger.info('dead connection')
break
# data (output) from pid
if pid.stdout in reads:
data = os.read(pid.stdout.fileno(), 64*1024)
if data:
# logger.debug('OUT:{}'.format(data))
conn.send(data)
else:
logger.info('dead stdout')
break
except:
logger.warning('woops disconnected')
finally:
try:
conn.close()
except:
pass
logger.info('disconnected')
if __name__ == "__main__":
basicConfig(level=os.environ.get('LOGLEVEL', 'INFO'))
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment