| #! /usr/bin/env python | |
| """A multi-threaded telnet-like server that gives a Python prompt. | |
| This is really a prototype for the same thing in C. | |
| Usage: pysvr.py [port] | |
| For security reasons, it only accepts requests from the current host. | |
| This can still be insecure, but restricts violations from people who | |
| can log in on your machine. Use with caution! | |
| """ | |
| import sys, os, string, getopt, thread, socket, traceback | |
| PORT = 4000 # Default port | |
| def main(): | |
| try: | |
| opts, args = getopt.getopt(sys.argv[1:], "") | |
| if len(args) > 1: | |
| raise getopt.error, "Too many arguments." | |
| except getopt.error, msg: | |
| usage(msg) | |
| for o, a in opts: | |
| pass | |
| if args: | |
| try: | |
| port = string.atoi(args[0]) | |
| except ValueError, msg: | |
| usage(msg) | |
| else: | |
| port = PORT | |
| main_thread(port) | |
| def usage(msg=None): | |
| sys.stdout = sys.stderr | |
| if msg: | |
| print msg | |
| print "\n", __doc__, | |
| sys.exit(2) | |
| def main_thread(port): | |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| sock.bind(("", port)) | |
| sock.listen(5) | |
| print "Listening on port", port, "..." | |
| while 1: | |
| (conn, addr) = sock.accept() | |
| if addr[0] != conn.getsockname()[0]: | |
| conn.close() | |
| print "Refusing connection from non-local host", addr[0], "." | |
| continue | |
| thread.start_new_thread(service_thread, (conn, addr)) | |
| del conn, addr | |
| def service_thread(conn, addr): | |
| (caddr, cport) = addr | |
| print "Thread %s has connection from %s.\n" % (str(thread.get_ident()), | |
| caddr), | |
| stdin = conn.makefile("r") | |
| stdout = conn.makefile("w", 0) | |
| run_interpreter(stdin, stdout) | |
| print "Thread %s is done.\n" % str(thread.get_ident()), | |
| def run_interpreter(stdin, stdout): | |
| globals = {} | |
| try: | |
| str(sys.ps1) | |
| except: | |
| sys.ps1 = ">>> " | |
| source = "" | |
| while 1: | |
| stdout.write(sys.ps1) | |
| line = stdin.readline() | |
| if line[:2] == '\377\354': | |
| line = "" | |
| if not line and not source: | |
| break | |
| if line[-2:] == '\r\n': | |
| line = line[:-2] + '\n' | |
| source = source + line | |
| try: | |
| code = compile_command(source) | |
| except SyntaxError, err: | |
| source = "" | |
| traceback.print_exception(SyntaxError, err, None, file=stdout) | |
| continue | |
| if not code: | |
| continue | |
| source = "" | |
| try: | |
| run_command(code, stdin, stdout, globals) | |
| except SystemExit, how: | |
| if how: | |
| try: | |
| how = str(how) | |
| except: | |
| how = "" | |
| stdout.write("Exit %s\n" % how) | |
| break | |
| stdout.write("\nGoodbye.\n") | |
| def run_command(code, stdin, stdout, globals): | |
| save = sys.stdin, sys.stdout, sys.stderr | |
| try: | |
| sys.stdout = sys.stderr = stdout | |
| sys.stdin = stdin | |
| try: | |
| exec code in globals | |
| except SystemExit, how: | |
| raise SystemExit, how, sys.exc_info()[2] | |
| except: | |
| type, value, tb = sys.exc_info() | |
| if tb: tb = tb.tb_next | |
| traceback.print_exception(type, value, tb) | |
| del tb | |
| finally: | |
| sys.stdin, sys.stdout, sys.stderr = save | |
| from code import compile_command | |
| main() |