1# Minimal interface to the Internet telnet protocol.
2#
3# *** modified to use threads ***
4#
5# It refuses all telnet options and does not recognize any of the other
6# telnet commands, but can still be used to connect in line-by-line mode.
7# It's also useful to play with a number of other services,
8# like time, finger, smtp and even ftp.
9#
10# Usage: telnet host [port]
11#
12# The port may be a service name or a decimal port number;
13# it defaults to 'telnet'.
14
15
16import sys, os, time
17from socket import *
18import thread
19
20BUFSIZE = 8*1024
21
22# Telnet protocol characters
23
24IAC  = chr(255) # Interpret as command
25DONT = chr(254)
26DO   = chr(253)
27WONT = chr(252)
28WILL = chr(251)
29
30def main():
31    if len(sys.argv) < 2:
32        sys.stderr.write('usage: telnet hostname [port]\n')
33        sys.exit(2)
34    host = sys.argv[1]
35    try:
36        hostaddr = gethostbyname(host)
37    except error:
38        sys.stderr.write(sys.argv[1] + ': bad host name\n')
39        sys.exit(2)
40    #
41    if len(sys.argv) > 2:
42        servname = sys.argv[2]
43    else:
44        servname = 'telnet'
45    #
46    if '0' <= servname[:1] <= '9':
47        port = eval(servname)
48    else:
49        try:
50            port = getservbyname(servname, 'tcp')
51        except error:
52            sys.stderr.write(servname + ': bad tcp service name\n')
53            sys.exit(2)
54    #
55    s = socket(AF_INET, SOCK_STREAM)
56    #
57    try:
58        s.connect((host, port))
59    except error, msg:
60        sys.stderr.write('connect failed: %r\n' % (msg,))
61        sys.exit(1)
62    #
63    thread.start_new(child, (s,))
64    parent(s)
65
66def parent(s):
67    # read socket, write stdout
68    iac = 0         # Interpret next char as command
69    opt = ''        # Interpret next char as option
70    while 1:
71        data, dummy = s.recvfrom(BUFSIZE)
72        if not data:
73            # EOF -- exit
74            sys.stderr.write( '(Closed by remote host)\n')
75            sys.exit(1)
76        cleandata = ''
77        for c in data:
78            if opt:
79                print ord(c)
80##                              print '(replying: %r)' % (opt+c,)
81                s.send(opt + c)
82                opt = ''
83            elif iac:
84                iac = 0
85                if c == IAC:
86                    cleandata = cleandata + c
87                elif c in (DO, DONT):
88                    if c == DO: print '(DO)',
89                    else: print '(DONT)',
90                    opt = IAC + WONT
91                elif c in (WILL, WONT):
92                    if c == WILL: print '(WILL)',
93                    else: print '(WONT)',
94                    opt = IAC + DONT
95                else:
96                    print '(command)', ord(c)
97            elif c == IAC:
98                iac = 1
99                print '(IAC)',
100            else:
101                cleandata = cleandata + c
102        sys.stdout.write(cleandata)
103        sys.stdout.flush()
104##              print 'Out:', repr(cleandata)
105
106def child(s):
107    # read stdin, write socket
108    while 1:
109        line = sys.stdin.readline()
110##              print 'Got:', repr(line)
111        if not line: break
112        s.send(line)
113
114main()
115