1 #! /usr/bin/env python 2 3 """A multi-threaded telnet-like server that gives a Python prompt. 4 5 This is really a prototype for the same thing in C. 6 7 Usage: pysvr.py [port] 8 9 For security reasons, it only accepts requests from the current host. 10 This can still be insecure, but restricts violations from people who 11 can log in on your machine. Use with caution! 12 13 """ 14 15 import sys, os, string, getopt, thread, socket, traceback 16 17 PORT = 4000 # Default port 18 19 def main(): 20 try: 21 opts, args = getopt.getopt(sys.argv[1:], "") 22 if len(args) > 1: 23 raise getopt.error, "Too many arguments." 24 except getopt.error, msg: 25 usage(msg) 26 for o, a in opts: 27 pass 28 if args: 29 try: 30 port = string.atoi(args[0]) 31 except ValueError, msg: 32 usage(msg) 33 else: 34 port = PORT 35 main_thread(port) 36 37 def usage(msg=None): 38 sys.stdout = sys.stderr 39 if msg: 40 print msg 41 print "\n", __doc__, 42 sys.exit(2) 43 44 def main_thread(port): 45 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 46 sock.bind(("", port)) 47 sock.listen(5) 48 print "Listening on port", port, "..." 49 while 1: 50 (conn, addr) = sock.accept() 51 if addr[0] != conn.getsockname()[0]: 52 conn.close() 53 print "Refusing connection from non-local host", addr[0], "." 54 continue 55 thread.start_new_thread(service_thread, (conn, addr)) 56 del conn, addr 57 58 def service_thread(conn, addr): 59 (caddr, cport) = addr 60 print "Thread %s has connection from %s.\n" % (str(thread.get_ident()), 61 caddr), 62 stdin = conn.makefile("r") 63 stdout = conn.makefile("w", 0) 64 run_interpreter(stdin, stdout) 65 print "Thread %s is done.\n" % str(thread.get_ident()), 66 67 def run_interpreter(stdin, stdout): 68 globals = {} 69 try: 70 str(sys.ps1) 71 except: 72 sys.ps1 = ">>> " 73 source = "" 74 while 1: 75 stdout.write(sys.ps1) 76 line = stdin.readline() 77 if line[:2] == '\377\354': 78 line = "" 79 if not line and not source: 80 break 81 if line[-2:] == '\r\n': 82 line = line[:-2] + '\n' 83 source = source + line 84 try: 85 code = compile_command(source) 86 except SyntaxError, err: 87 source = "" 88 traceback.print_exception(SyntaxError, err, None, file=stdout) 89 continue 90 if not code: 91 continue 92 source = "" 93 try: 94 run_command(code, stdin, stdout, globals) 95 except SystemExit, how: 96 if how: 97 try: 98 how = str(how) 99 except: 100 how = "" 101 stdout.write("Exit %s\n" % how) 102 break 103 stdout.write("\nGoodbye.\n") 104 105 def run_command(code, stdin, stdout, globals): 106 save = sys.stdin, sys.stdout, sys.stderr 107 try: 108 sys.stdout = sys.stderr = stdout 109 sys.stdin = stdin 110 try: 111 exec code in globals 112 except SystemExit, how: 113 raise SystemExit, how, sys.exc_info()[2] 114 except: 115 type, value, tb = sys.exc_info() 116 if tb: tb = tb.tb_next 117 traceback.print_exception(type, value, tb) 118 del tb 119 finally: 120 sys.stdin, sys.stdout, sys.stderr = save 121 122 from code import compile_command 123 124 main() 125