196a321dfSIngo Weinhold#!/usr/bin/env python
296a321dfSIngo Weinhold
396a321dfSIngo Weinholdimport socket
496a321dfSIngo Weinholdimport subprocess
596a321dfSIngo Weinholdimport sys
696a321dfSIngo Weinhold
796a321dfSIngo Weinhold
896a321dfSIngo Weinholdaddress = '0.0.0.0'
996a321dfSIngo Weinholdport = 4242
1096a321dfSIngo Weinhold
1196a321dfSIngo Weinhold
1296a321dfSIngo Weinholddef receiveExactly(connection, size):
1396a321dfSIngo Weinhold	data = '';
1496a321dfSIngo Weinhold	while size > 0:
1596a321dfSIngo Weinhold		dataReceived = connection.recv(size)
1696a321dfSIngo Weinhold		if not dataReceived:
1796a321dfSIngo Weinhold			raise EOFError()
1896a321dfSIngo Weinhold		data += dataReceived
1996a321dfSIngo Weinhold		size -= len(dataReceived)
2096a321dfSIngo Weinhold	return data
2196a321dfSIngo Weinhold
2296a321dfSIngo Weinhold
2396a321dfSIngo Weinholddef handleConnection(listenerSocket):
2496a321dfSIngo Weinhold	(controlConnection, controlAddress) = listenerSocket.accept()
2596a321dfSIngo Weinhold	(stdioConnection, stdioAddress) = listenerSocket.accept()
2696a321dfSIngo Weinhold	(stderrConnection, stderrAddress) = listenerSocket.accept()
2796a321dfSIngo Weinhold
2896a321dfSIngo Weinhold	print 'accepted client connections'
2996a321dfSIngo Weinhold
3096a321dfSIngo Weinhold	try:
3196a321dfSIngo Weinhold		commandLength = receiveExactly(controlConnection, 8)
3296a321dfSIngo Weinhold		commandToRun = receiveExactly(controlConnection, int(commandLength))
3396a321dfSIngo Weinhold
3496a321dfSIngo Weinhold		print 'received command: ' + commandToRun
3596a321dfSIngo Weinhold
3696a321dfSIngo Weinhold		exitCode = subprocess.call(commandToRun, stdin=stdioConnection,
3796a321dfSIngo Weinhold			stdout=stdioConnection, stderr=stderrConnection, shell=True)
3896a321dfSIngo Weinhold
3996a321dfSIngo Weinhold		controlConnection.send(str(exitCode))
4096a321dfSIngo Weinhold	finally:
4196a321dfSIngo Weinhold		controlConnection.close()
4296a321dfSIngo Weinhold		stdioConnection.close()
4396a321dfSIngo Weinhold		stderrConnection.close()
4496a321dfSIngo Weinhold
4596a321dfSIngo Weinhold	print 'client connections closed'
4696a321dfSIngo Weinhold
4796a321dfSIngo Weinhold
4896a321dfSIngo WeinholdlistenerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4996a321dfSIngo WeinholdlistenerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
5096a321dfSIngo Weinhold
5196a321dfSIngo Weinholdtry:
5296a321dfSIngo Weinhold	listenerSocket.bind((address, port))
5396a321dfSIngo Weinholdexcept socket.error, msg:
5496a321dfSIngo Weinhold	sys.exit('Failed to bind to %s port %d: %s' % (address, port, msg[1]))
5596a321dfSIngo Weinhold
5696a321dfSIngo WeinholdlistenerSocket.listen(3)
5796a321dfSIngo Weinhold
5896a321dfSIngo Weinholdprint 'started listening on adddress %s port %s' % (address, port)
5996a321dfSIngo Weinhold
6096a321dfSIngo Weinholdwhile True:
6196a321dfSIngo Weinhold	handleConnection(listenerSocket)
62