#!/usr/bin/env ruby

require 'optparse'
require 'socket'

usage = 'Usage: tcplol [-2v] [-h 127.0.0.1] -p 1234 program [args...]'
opt = ARGV.getopts 'h:p:2v'
abort usage unless opt['p'] && ARGV[0]
$VERBOSE = nil unless opt['v']

at_exit do
  Thread.list.filter { |t| t != Thread.current }.each do |t|
    warn "\n Waiting for #{t[:cid]}"
    t.join
  end
end

server = TCPServer.new opt['h'] || '127.0.0.1', opt['p']
loop do
  begin
    client = server.accept
    cid = client.remote_address.ip_unpack.join ':'
  rescue StandardError
    warn "Client error: #{$!}"
    next
  end

  warn "Client #{cid}"
  pid = fork do
    $stdin.reopen client
    $stdout.reopen client
    $stderr.reopen client if opt['2']
    client.close
    exec(*ARGV)
  end
  client.close
  cid += ", pid #{pid}"
  Thread.new(cid, pid) do
    Thread.current[:cid] = cid
    Process.wait pid
    warn "Client #{cid}: disconnect"
  end
end
