1210006Srdivacky#!/usr/bin/env python
2210006Srdivacky#
3210006Srdivacky# Usage: bootstrap_client.py <address>[:port] <command> ...
4210006Srdivacky#
5210006Srdivacky# <command> and the following arguments are concatenated (separated by a space)
6210006Srdivacky# and passed to a shell on the server.
7210006Srdivacky
8210006Srdivackyimport os
9210006Srdivackyimport select
10210006Srdivackyimport socket
11210006Srdivackyimport sys
12210006Srdivacky
13252723Sdim
14210006Srdivackyport = 4242
15210006SrdivackybufferSize = 4 * 1024
16210006Srdivacky
17210006Srdivacky# interpret command line args
18210006Srdivackyif len(sys.argv) < 3:
19210006Srdivacky	sys.exit('Usage: ' + sys.argv[0] + ' <address>[:<port>] <command>')
20212904Sdim
21212904Sdimaddress = sys.argv[1]
22212904SdimportIndex = address.find(':')
23226890Sdimif portIndex >= 0:
24210006Srdivacky	port = int(address[portIndex + 1:])
25210006Srdivacky	address = address[:portIndex]
26210006Srdivacky
27210006SrdivackycommandToRun = " ".join(sys.argv[2:])
28210006Srdivacky
29210006Srdivacky# create sockets and connect to server
30210006SrdivackycontrolConnection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
31210006SrdivackystdioConnection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
32210006SrdivackystderrConnection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
33210006Srdivacky
34210006Srdivackytry:
35210006Srdivacky	controlConnection.connect((address, port))
36252723Sdim	stdioConnection.connect((address, port))
37210006Srdivacky	stderrConnection.connect((address, port))
38218893Sdimexcept socket.error, msg:
39235633Sdim	sys.exit('Failed to connect to %s port %d: %s' % (address, port, msg[1]))
40235633Sdim
41218893Sdim# send command length and command
42210006SrdivackycontrolConnection.send("%08d" % len(commandToRun))
43263509SdimcontrolConnection.send(commandToRun)
44263509Sdim
45263509Sdim# I/O loop. We quit when all sockets have been closed.
46263509SdimexitCode = ''
47263509Sdimconnections = [controlConnection, stdioConnection, stderrConnection, sys.stdin]
48221345Sdim
49210006Srdivackywhile connections and (len(connections) > 1 or not sys.stdin in connections):
50210006Srdivacky	(readable, writable, exceptions) = select.select(connections, [],
51252723Sdim		connections)
52252723Sdim
53252723Sdim	if sys.stdin in readable:
54252723Sdim		data = sys.stdin.readline(bufferSize)
55252723Sdim		if data:
56210006Srdivacky			stdioConnection.send(data)
57210006Srdivacky		else:
58210006Srdivacky			connections.remove(sys.stdin)
59210006Srdivacky			stdioConnection.shutdown(socket.SHUT_WR)
60212904Sdim
61212904Sdim	if stdioConnection in readable:
62252723Sdim		data = stdioConnection.recv(bufferSize)
63252723Sdim		if data:
64252723Sdim			sys.stdout.write(data)
65252723Sdim		else:
66252723Sdim			connections.remove(stdioConnection)
67212904Sdim
68212904Sdim	if stderrConnection in readable:
69212904Sdim		data = stderrConnection.recv(bufferSize)
70212904Sdim		if data:
71212904Sdim			sys.stderr.write(data)
72212904Sdim		else:
73210006Srdivacky			connections.remove(stderrConnection)
74210006Srdivacky
75210006Srdivacky	if controlConnection in readable:
76210006Srdivacky		data = controlConnection.recv(bufferSize)
77210006Srdivacky		if data:
78210006Srdivacky			exitCode += data
79218893Sdim		else:
80252723Sdim			connections.remove(controlConnection)
81252723Sdim
82263509Sdim# either an exit code has been sent or we consider this an error
83221345Sdimif exitCode:
84221345Sdim	sys.exit(int(exitCode))
85218893Sdimsys.exit(1)
86252723Sdim