|
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() |