#!/usr/bin/env python

from __future__ import print_function

import os, sys
import subprocess
import tempfile
import signal

argiter = iter(sys.argv)
progname = next(argiter)
daemonize = False
show_stderr = False

def usage():
    print('Usage: %s [options] port command ...' % sys.argv[0])
    print('Options:')
    print('  -d       Daemonize')
    print('  -e       Redirect program\'s stderr to socket')
    sys.exit(1)

for arg in argiter:
    if arg == '-d':
        daemonize = True
    elif arg == '-e':
        show_stderr = True
    else:
        break
else:
    usage()

try:
    port = int(arg) # pylint: disable=undefined-loop-variable
except (ValueError, NameError):
    usage()

def quote(s):
    return "'%s'" % s.replace("'", "'\"'\"'")

command = ' '.join(map(quote, argiter))
if command == '':
    usage()

if daemonize:
    p = os.fork()
    if p:
        print(p)
        sys.stdout.flush()
        os._exit(0)

with tempfile.NamedTemporaryFile(delete=False) as tf:
    tf.write(b'#!/bin/bash\nexec %s\n' % command.encode('utf-8'))
os.chmod(tf.name, 0o755)

cmd = ['/usr/bin/socat', 'TCP-LISTEN:%d,reuseaddr,fork' % port, 'EXEC:%s' % tf.name]
if show_stderr:
    cmd[-1] += ',stderr'

extra_args = {'close_fds': True}
if daemonize:
    NULL = open(os.devnull, 'r+')
    extra_args['stdin'] = NULL
    extra_args['stdout'] = NULL
    extra_args['stderr'] = NULL

# launch!
p = subprocess.Popen(cmd, **extra_args)

def onstop(signo, stack): # pylint: disable=unused-argument
    os.unlink(tf.name)
    try:
        p.kill()
    except OSError:
        pass
    sys.exit(0)

signal.signal(signal.SIGTERM, onstop)
signal.signal(signal.SIGINT, onstop)

p.wait()
onstop(None, None)
