103 lines
3.0 KiB
Python
Executable File
103 lines
3.0 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
"""
|
|
start socket based minimal readline exec server
|
|
"""
|
|
# this part of the program only executes on the server side
|
|
#
|
|
|
|
progname = 'socket_readline_exec_server-1.2'
|
|
|
|
import sys, socket, os
|
|
try:
|
|
import fcntl
|
|
except ImportError:
|
|
fcntl = None
|
|
|
|
debug = 0
|
|
|
|
if debug: # and not os.isatty(sys.stdin.fileno()):
|
|
f = open('/tmp/execnet-socket-pyout.log', 'w')
|
|
old = sys.stdout, sys.stderr
|
|
sys.stdout = sys.stderr = f
|
|
#import py
|
|
#compile = py.code.compile
|
|
|
|
def print_(*args):
|
|
print(" ".join(str(arg) for arg in args))
|
|
|
|
if sys.version_info > (3, 0):
|
|
exec("""def exec_(source, locs):
|
|
exec(source, locs)""")
|
|
else:
|
|
exec("""def exec_(source, locs):
|
|
exec source in locs""")
|
|
|
|
def exec_from_one_connection(serversock):
|
|
print_(progname, 'Entering Accept loop', serversock.getsockname())
|
|
clientsock,address = serversock.accept()
|
|
print_(progname, 'got new connection from %s %s' % address)
|
|
clientfile = clientsock.makefile('rb')
|
|
print_("reading line")
|
|
# rstrip so that we can use \r\n for telnet testing
|
|
source = clientfile.readline().rstrip()
|
|
clientfile.close()
|
|
g = {'clientsock' : clientsock, 'address' : address}
|
|
source = eval(source)
|
|
if source:
|
|
co = compile(source+'\n', source, 'exec')
|
|
print_(progname, 'compiled source, executing')
|
|
try:
|
|
exec_(co, g)
|
|
finally:
|
|
print_(progname, 'finished executing code')
|
|
# background thread might hold a reference to this (!?)
|
|
#clientsock.close()
|
|
|
|
def bind_and_listen(hostport):
|
|
if isinstance(hostport, str):
|
|
host, port = hostport.split(':')
|
|
hostport = (host, int(port))
|
|
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
# set close-on-exec
|
|
if hasattr(fcntl, 'FD_CLOEXEC'):
|
|
old = fcntl.fcntl(serversock.fileno(), fcntl.F_GETFD)
|
|
fcntl.fcntl(serversock.fileno(), fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
|
|
# allow the address to be re-used in a reasonable amount of time
|
|
if os.name == 'posix' and sys.platform != 'cygwin':
|
|
serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
|
|
serversock.bind(hostport)
|
|
serversock.listen(5)
|
|
return serversock
|
|
|
|
def startserver(serversock, loop=False):
|
|
try:
|
|
while 1:
|
|
try:
|
|
exec_from_one_connection(serversock)
|
|
except (KeyboardInterrupt, SystemExit):
|
|
raise
|
|
except:
|
|
if debug:
|
|
import traceback
|
|
traceback.print_exc()
|
|
else:
|
|
excinfo = sys.exc_info()
|
|
print_("got exception", excinfo[1])
|
|
if not loop:
|
|
break
|
|
finally:
|
|
print_("leaving socketserver execloop")
|
|
serversock.shutdown(2)
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
if len(sys.argv)>1:
|
|
hostport = sys.argv[1]
|
|
else:
|
|
hostport = ':8888'
|
|
serversock = bind_and_listen(hostport)
|
|
startserver(serversock, loop=False)
|
|
|