-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkombug.py
executable file
·179 lines (165 loc) · 5.07 KB
/
kombug.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#! /usr/bin/env python
# This program is a LysKOM protocol A bugging program. It listens to
# a port, and when a LysKOM client connects to that port it will
# connect to a LysKOM server. All data between the client and the
# server will be enqueued by this program.
#
# This bugging program is interactive. The prompt, which is printed
# in reverse video, indicates how many pending questions/replies/async
# messages there are. When the user hits "c" one pending question
# will be forwarded to the server (and printed to stdout in reverse
# video). When the user hits "s" one pending reply or async message
# is forwarded from the server to the client (and printed to stdout).
#
# Hit "q" to exit kombug.py.
#
# Sample usage:
#
# ./kombug.py 5100 kom.lysator.liu.se 4894
#
# This will listen to port 5100 and forward connections to
# kom.lysator.liu.se:4894. The two last arguments may be left out.
#
# BUGS:
# The "c" and "s" buttons may wear out.
# Inverse video assumes that a vt100-compatible output device is used.
import os
import sys
import socket
import select
import string
def encode(s):
res = ""
for c in s:
if c == "\\":
res += "\\\\"
elif (ord(c) >= 32 and ord(c) < 127) or c == "\n":
res += c
elif ord(c) < 256:
res += "\\x%02x" % ord(c)
else:
res += "\\badchar(%d)" % ord(c)
return res
class kombug:
def __init__(self, myport, host, port):
self.clientq=[]
self.serverq=[]
self.clientunparsed=""
self.serverunparsed=""
self.connect(host, port)
self.listen(myport)
def connect(self, host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((host, port))
print "Reached", host, port
self.server = s
def listen(self, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("", port))
s.listen(3)
(self.client, addr) = s.accept()
print "Client connected from", addr
def prompt(self):
self.current_prompt=("Client: " + `len(self.clientq)`
+ " Server: " + `len(self.serverq)` + ": ")
sys.stdout.write(self.current_prompt)
sys.stdout.flush()
def eraseprompt(self):
sys.stdout.write("\r" + " "*len(self.current_prompt) + "\r")
sys.stdout.flush()
def parse(self, str, res):
"""Parse calls from STR and append them to RES.
RES is a list of strings. STR is a string. Any unparsed data
are returned. That happens if an incomplete call exists in STR.
"""
linestart=0
state=0
i=0
while i < len(str):
c = str[i]
if c == '\n':
res.append(str[linestart:i+1])
linestart=i+1
state = 0
elif state == 0:
if c in string.digits:
stringstart=i
state = 1
elif state == 1:
if c == "H":
slen=string.atoi(str[stringstart:i])
i = i + slen
state = 0
elif c not in string.digits:
state = 0
i = i + 1
return str[linestart:]
def relay(self, fastmode):
try:
os.system("stty -echo -icanon min 1 time 0 -opost")
while 1:
self.prompt()
timeout = None
if fastmode and len(self.clientq) + len(self.serverq) > 0:
timeout = 0.0
(rfd, wfd, efd) = select.select([self.server, self.client,
sys.stdin.fileno()], [], [],
timeout)
self.eraseprompt()
if self.server in rfd:
msg=self.server.recv(10000)
if msg == "":
sys.stdout.write("[eof from server]\r\n")
return
self.serverunparsed = self.parse(
self.serverunparsed + msg, self.serverq)
if self.client in rfd:
msg=self.client.recv(1000)
if msg == "":
sys.stdout.write("[eof from client]\r\n")
return
self.clientunparsed = self.parse(
self.clientunparsed + msg, self.clientq)
key = None
if sys.stdin.fileno() in rfd:
key=sys.stdin.read(1)
if key == "q":
return
if key == "c" or fastmode:
if len(self.clientq) > 0:
msg=self.clientq[0]
self.server.send(msg)
self.clientq[0:1]=[]
sys.stdout.write("\033[7m" + encode(msg) + "\033[m\r")
sys.stdout.flush()
elif not fastmode:
sys.stdout.write('\a')
if key == "s" or fastmode:
if len(self.serverq) > 0:
msg=self.serverq[0]
self.client.send(msg)
self.serverq[0:1]=[]
sys.stdout.write(encode(msg) + "\r")
sys.stdout.flush()
elif not fastmode:
sys.stdout.write('\a')
if key == "a":
fastmode = not fastmode
if key != None and key != "c" and key != "s" and key != "a":
sys.stdout.write('\a')
finally:
os.system("stty echo icanon opost");
if __name__ == '__main__':
local_port = string.atoi(sys.argv[1])
if len(sys.argv) > 2:
remote_host = sys.argv[2]
else:
remote_host = "kom.lysator.liu.se"
if len(sys.argv) > 3:
remote_port = string.atoi(sys.argv[3])
else:
remote_port = 4894
b=kombug(local_port, remote_host, remote_port)
b.relay(0)