source: titan/mediathek/localhoster/lib/python2.7/telnetlib.py @ 40523

Last change on this file since 40523 was 40094, checked in by obi, 7 years ago

tithek add yoztube-dl support

File size: 26.4 KB
Line 
1r"""TELNET client class.
2
3Based on RFC 854: TELNET Protocol Specification, by J. Postel and
4J. Reynolds
5
6Example:
7
8>>> from telnetlib import Telnet
9>>> tn = Telnet('www.python.org', 79)   # connect to finger port
10>>> tn.write('guido\r\n')
11>>> print tn.read_all()
12Login       Name               TTY         Idle    When    Where
13guido    Guido van Rossum      pts/2        <Dec  2 11:10> snag.cnri.reston..
14
15>>>
16
17Note that read_all() won't read until eof -- it just reads some data
18-- but it guarantees to read at least one byte unless EOF is hit.
19
20It is possible to pass a Telnet object to select.select() in order to
21wait until more data is available.  Note that in this case,
22read_eager() may return '' even if there was data on the socket,
23because the protocol negotiation may have eaten the data.  This is why
24EOFError is needed in some cases to distinguish between "no data" and
25"connection closed" (since the socket also appears ready for reading
26when it is closed).
27
28To do:
29- option negotiation
30- timeout should be intrinsic to the connection object instead of an
31  option on one of the read calls only
32
33"""
34
35
36# Imported modules
37import errno
38import sys
39import socket
40import select
41
42__all__ = ["Telnet"]
43
44# Tunable parameters
45DEBUGLEVEL = 0
46
47# Telnet protocol defaults
48TELNET_PORT = 23
49
50# Telnet protocol characters (don't change)
51IAC  = chr(255) # "Interpret As Command"
52DONT = chr(254)
53DO   = chr(253)
54WONT = chr(252)
55WILL = chr(251)
56theNULL = chr(0)
57
58SE  = chr(240)  # Subnegotiation End
59NOP = chr(241)  # No Operation
60DM  = chr(242)  # Data Mark
61BRK = chr(243)  # Break
62IP  = chr(244)  # Interrupt process
63AO  = chr(245)  # Abort output
64AYT = chr(246)  # Are You There
65EC  = chr(247)  # Erase Character
66EL  = chr(248)  # Erase Line
67GA  = chr(249)  # Go Ahead
68SB =  chr(250)  # Subnegotiation Begin
69
70
71# Telnet protocol options code (don't change)
72# These ones all come from arpa/telnet.h
73BINARY = chr(0) # 8-bit data path
74ECHO = chr(1) # echo
75RCP = chr(2) # prepare to reconnect
76SGA = chr(3) # suppress go ahead
77NAMS = chr(4) # approximate message size
78STATUS = chr(5) # give status
79TM = chr(6) # timing mark
80RCTE = chr(7) # remote controlled transmission and echo
81NAOL = chr(8) # negotiate about output line width
82NAOP = chr(9) # negotiate about output page size
83NAOCRD = chr(10) # negotiate about CR disposition
84NAOHTS = chr(11) # negotiate about horizontal tabstops
85NAOHTD = chr(12) # negotiate about horizontal tab disposition
86NAOFFD = chr(13) # negotiate about formfeed disposition
87NAOVTS = chr(14) # negotiate about vertical tab stops
88NAOVTD = chr(15) # negotiate about vertical tab disposition
89NAOLFD = chr(16) # negotiate about output LF disposition
90XASCII = chr(17) # extended ascii character set
91LOGOUT = chr(18) # force logout
92BM = chr(19) # byte macro
93DET = chr(20) # data entry terminal
94SUPDUP = chr(21) # supdup protocol
95SUPDUPOUTPUT = chr(22) # supdup output
96SNDLOC = chr(23) # send location
97TTYPE = chr(24) # terminal type
98EOR = chr(25) # end or record
99TUID = chr(26) # TACACS user identification
100OUTMRK = chr(27) # output marking
101TTYLOC = chr(28) # terminal location number
102VT3270REGIME = chr(29) # 3270 regime
103X3PAD = chr(30) # X.3 PAD
104NAWS = chr(31) # window size
105TSPEED = chr(32) # terminal speed
106LFLOW = chr(33) # remote flow control
107LINEMODE = chr(34) # Linemode option
108XDISPLOC = chr(35) # X Display Location
109OLD_ENVIRON = chr(36) # Old - Environment variables
110AUTHENTICATION = chr(37) # Authenticate
111ENCRYPT = chr(38) # Encryption option
112NEW_ENVIRON = chr(39) # New - Environment variables
113# the following ones come from
114# http://www.iana.org/assignments/telnet-options
115# Unfortunately, that document does not assign identifiers
116# to all of them, so we are making them up
117TN3270E = chr(40) # TN3270E
118XAUTH = chr(41) # XAUTH
119CHARSET = chr(42) # CHARSET
120RSP = chr(43) # Telnet Remote Serial Port
121COM_PORT_OPTION = chr(44) # Com Port Control Option
122SUPPRESS_LOCAL_ECHO = chr(45) # Telnet Suppress Local Echo
123TLS = chr(46) # Telnet Start TLS
124KERMIT = chr(47) # KERMIT
125SEND_URL = chr(48) # SEND-URL
126FORWARD_X = chr(49) # FORWARD_X
127PRAGMA_LOGON = chr(138) # TELOPT PRAGMA LOGON
128SSPI_LOGON = chr(139) # TELOPT SSPI LOGON
129PRAGMA_HEARTBEAT = chr(140) # TELOPT PRAGMA HEARTBEAT
130EXOPL = chr(255) # Extended-Options-List
131NOOPT = chr(0)
132
133class Telnet:
134
135    """Telnet interface class.
136
137    An instance of this class represents a connection to a telnet
138    server.  The instance is initially not connected; the open()
139    method must be used to establish a connection.  Alternatively, the
140    host name and optional port number can be passed to the
141    constructor, too.
142
143    Don't try to reopen an already connected instance.
144
145    This class has many read_*() methods.  Note that some of them
146    raise EOFError when the end of the connection is read, because
147    they can return an empty string for other reasons.  See the
148    individual doc strings.
149
150    read_until(expected, [timeout])
151        Read until the expected string has been seen, or a timeout is
152        hit (default is no timeout); may block.
153
154    read_all()
155        Read all data until EOF; may block.
156
157    read_some()
158        Read at least one byte or EOF; may block.
159
160    read_very_eager()
161        Read all data available already queued or on the socket,
162        without blocking.
163
164    read_eager()
165        Read either data already queued or some data available on the
166        socket, without blocking.
167
168    read_lazy()
169        Read all data in the raw queue (processing it first), without
170        doing any socket I/O.
171
172    read_very_lazy()
173        Reads all data in the cooked queue, without doing any socket
174        I/O.
175
176    read_sb_data()
177        Reads available data between SB ... SE sequence. Don't block.
178
179    set_option_negotiation_callback(callback)
180        Each time a telnet option is read on the input flow, this callback
181        (if set) is called with the following parameters :
182        callback(telnet socket, command, option)
183            option will be chr(0) when there is no option.
184        No other action is done afterwards by telnetlib.
185
186    """
187
188    def __init__(self, host=None, port=0,
189                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
190        """Constructor.
191
192        When called without arguments, create an unconnected instance.
193        With a hostname argument, it connects the instance; port number
194        and timeout are optional.
195        """
196        self.debuglevel = DEBUGLEVEL
197        self.host = host
198        self.port = port
199        self.timeout = timeout
200        self.sock = None
201        self.rawq = ''
202        self.irawq = 0
203        self.cookedq = ''
204        self.eof = 0
205        self.iacseq = '' # Buffer for IAC sequence.
206        self.sb = 0 # flag for SB and SE sequence.
207        self.sbdataq = ''
208        self.option_callback = None
209        self._has_poll = hasattr(select, 'poll')
210        if host is not None:
211            self.open(host, port, timeout)
212
213    def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
214        """Connect to a host.
215
216        The optional second argument is the port number, which
217        defaults to the standard telnet port (23).
218
219        Don't try to reopen an already connected instance.
220        """
221        self.eof = 0
222        if not port:
223            port = TELNET_PORT
224        self.host = host
225        self.port = port
226        self.timeout = timeout
227        self.sock = socket.create_connection((host, port), timeout)
228
229    def __del__(self):
230        """Destructor -- close the connection."""
231        self.close()
232
233    def msg(self, msg, *args):
234        """Print a debug message, when the debug level is > 0.
235
236        If extra arguments are present, they are substituted in the
237        message using the standard string formatting operator.
238
239        """
240        if self.debuglevel > 0:
241            print 'Telnet(%s,%s):' % (self.host, self.port),
242            if args:
243                print msg % args
244            else:
245                print msg
246
247    def set_debuglevel(self, debuglevel):
248        """Set the debug level.
249
250        The higher it is, the more debug output you get (on sys.stdout).
251
252        """
253        self.debuglevel = debuglevel
254
255    def close(self):
256        """Close the connection."""
257        sock = self.sock
258        self.sock = 0
259        self.eof = 1
260        self.iacseq = ''
261        self.sb = 0
262        if sock:
263            sock.close()
264
265    def get_socket(self):
266        """Return the socket object used internally."""
267        return self.sock
268
269    def fileno(self):
270        """Return the fileno() of the socket object used internally."""
271        return self.sock.fileno()
272
273    def write(self, buffer):
274        """Write a string to the socket, doubling any IAC characters.
275
276        Can block if the connection is blocked.  May raise
277        socket.error if the connection is closed.
278
279        """
280        if IAC in buffer:
281            buffer = buffer.replace(IAC, IAC+IAC)
282        self.msg("send %r", buffer)
283        self.sock.sendall(buffer)
284
285    def read_until(self, match, timeout=None):
286        """Read until a given string is encountered or until timeout.
287
288        When no match is found, return whatever is available instead,
289        possibly the empty string.  Raise EOFError if the connection
290        is closed and no cooked data is available.
291
292        """
293        if self._has_poll:
294            return self._read_until_with_poll(match, timeout)
295        else:
296            return self._read_until_with_select(match, timeout)
297
298    def _read_until_with_poll(self, match, timeout):
299        """Read until a given string is encountered or until timeout.
300
301        This method uses select.poll() to implement the timeout.
302        """
303        n = len(match)
304        call_timeout = timeout
305        if timeout is not None:
306            from time import time
307            time_start = time()
308        self.process_rawq()
309        i = self.cookedq.find(match)
310        if i < 0:
311            poller = select.poll()
312            poll_in_or_priority_flags = select.POLLIN | select.POLLPRI
313            poller.register(self, poll_in_or_priority_flags)
314            while i < 0 and not self.eof:
315                try:
316                    # Poll takes its timeout in milliseconds.
317                    ready = poller.poll(None if timeout is None
318                                        else 1000 * call_timeout)
319                except select.error as e:
320                    if e.errno == errno.EINTR:
321                        if timeout is not None:
322                            elapsed = time() - time_start
323                            call_timeout = timeout-elapsed
324                        continue
325                    raise
326                for fd, mode in ready:
327                    if mode & poll_in_or_priority_flags:
328                        i = max(0, len(self.cookedq)-n)
329                        self.fill_rawq()
330                        self.process_rawq()
331                        i = self.cookedq.find(match, i)
332                if timeout is not None:
333                    elapsed = time() - time_start
334                    if elapsed >= timeout:
335                        break
336                    call_timeout = timeout-elapsed
337            poller.unregister(self)
338        if i >= 0:
339            i = i + n
340            buf = self.cookedq[:i]
341            self.cookedq = self.cookedq[i:]
342            return buf
343        return self.read_very_lazy()
344
345    def _read_until_with_select(self, match, timeout=None):
346        """Read until a given string is encountered or until timeout.
347
348        The timeout is implemented using select.select().
349        """
350        n = len(match)
351        self.process_rawq()
352        i = self.cookedq.find(match)
353        if i >= 0:
354            i = i+n
355            buf = self.cookedq[:i]
356            self.cookedq = self.cookedq[i:]
357            return buf
358        s_reply = ([self], [], [])
359        s_args = s_reply
360        if timeout is not None:
361            s_args = s_args + (timeout,)
362            from time import time
363            time_start = time()
364        while not self.eof and select.select(*s_args) == s_reply:
365            i = max(0, len(self.cookedq)-n)
366            self.fill_rawq()
367            self.process_rawq()
368            i = self.cookedq.find(match, i)
369            if i >= 0:
370                i = i+n
371                buf = self.cookedq[:i]
372                self.cookedq = self.cookedq[i:]
373                return buf
374            if timeout is not None:
375                elapsed = time() - time_start
376                if elapsed >= timeout:
377                    break
378                s_args = s_reply + (timeout-elapsed,)
379        return self.read_very_lazy()
380
381    def read_all(self):
382        """Read all data until EOF; block until connection closed."""
383        self.process_rawq()
384        while not self.eof:
385            self.fill_rawq()
386            self.process_rawq()
387        buf = self.cookedq
388        self.cookedq = ''
389        return buf
390
391    def read_some(self):
392        """Read at least one byte of cooked data unless EOF is hit.
393
394        Return '' if EOF is hit.  Block if no data is immediately
395        available.
396
397        """
398        self.process_rawq()
399        while not self.cookedq and not self.eof:
400            self.fill_rawq()
401            self.process_rawq()
402        buf = self.cookedq
403        self.cookedq = ''
404        return buf
405
406    def read_very_eager(self):
407        """Read everything that's possible without blocking in I/O (eager).
408
409        Raise EOFError if connection closed and no cooked data
410        available.  Return '' if no cooked data available otherwise.
411        Don't block unless in the midst of an IAC sequence.
412
413        """
414        self.process_rawq()
415        while not self.eof and self.sock_avail():
416            self.fill_rawq()
417            self.process_rawq()
418        return self.read_very_lazy()
419
420    def read_eager(self):
421        """Read readily available data.
422
423        Raise EOFError if connection closed and no cooked data
424        available.  Return '' if no cooked data available otherwise.
425        Don't block unless in the midst of an IAC sequence.
426
427        """
428        self.process_rawq()
429        while not self.cookedq and not self.eof and self.sock_avail():
430            self.fill_rawq()
431            self.process_rawq()
432        return self.read_very_lazy()
433
434    def read_lazy(self):
435        """Process and return data that's already in the queues (lazy).
436
437        Raise EOFError if connection closed and no data available.
438        Return '' if no cooked data available otherwise.  Don't block
439        unless in the midst of an IAC sequence.
440
441        """
442        self.process_rawq()
443        return self.read_very_lazy()
444
445    def read_very_lazy(self):
446        """Return any data available in the cooked queue (very lazy).
447
448        Raise EOFError if connection closed and no data available.
449        Return '' if no cooked data available otherwise.  Don't block.
450
451        """
452        buf = self.cookedq
453        self.cookedq = ''
454        if not buf and self.eof and not self.rawq:
455            raise EOFError, 'telnet connection closed'
456        return buf
457
458    def read_sb_data(self):
459        """Return any data available in the SB ... SE queue.
460
461        Return '' if no SB ... SE available. Should only be called
462        after seeing a SB or SE command. When a new SB command is
463        found, old unread SB data will be discarded. Don't block.
464
465        """
466        buf = self.sbdataq
467        self.sbdataq = ''
468        return buf
469
470    def set_option_negotiation_callback(self, callback):
471        """Provide a callback function called after each receipt of a telnet option."""
472        self.option_callback = callback
473
474    def process_rawq(self):
475        """Transfer from raw queue to cooked queue.
476
477        Set self.eof when connection is closed.  Don't block unless in
478        the midst of an IAC sequence.
479
480        """
481        buf = ['', '']
482        try:
483            while self.rawq:
484                c = self.rawq_getchar()
485                if not self.iacseq:
486                    if c == theNULL:
487                        continue
488                    if c == "\021":
489                        continue
490                    if c != IAC:
491                        buf[self.sb] = buf[self.sb] + c
492                        continue
493                    else:
494                        self.iacseq += c
495                elif len(self.iacseq) == 1:
496                    # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
497                    if c in (DO, DONT, WILL, WONT):
498                        self.iacseq += c
499                        continue
500
501                    self.iacseq = ''
502                    if c == IAC:
503                        buf[self.sb] = buf[self.sb] + c
504                    else:
505                        if c == SB: # SB ... SE start.
506                            self.sb = 1
507                            self.sbdataq = ''
508                        elif c == SE:
509                            self.sb = 0
510                            self.sbdataq = self.sbdataq + buf[1]
511                            buf[1] = ''
512                        if self.option_callback:
513                            # Callback is supposed to look into
514                            # the sbdataq
515                            self.option_callback(self.sock, c, NOOPT)
516                        else:
517                            # We can't offer automatic processing of
518                            # suboptions. Alas, we should not get any
519                            # unless we did a WILL/DO before.
520                            self.msg('IAC %d not recognized' % ord(c))
521                elif len(self.iacseq) == 2:
522                    cmd = self.iacseq[1]
523                    self.iacseq = ''
524                    opt = c
525                    if cmd in (DO, DONT):
526                        self.msg('IAC %s %d',
527                            cmd == DO and 'DO' or 'DONT', ord(opt))
528                        if self.option_callback:
529                            self.option_callback(self.sock, cmd, opt)
530                        else:
531                            self.sock.sendall(IAC + WONT + opt)
532                    elif cmd in (WILL, WONT):
533                        self.msg('IAC %s %d',
534                            cmd == WILL and 'WILL' or 'WONT', ord(opt))
535                        if self.option_callback:
536                            self.option_callback(self.sock, cmd, opt)
537                        else:
538                            self.sock.sendall(IAC + DONT + opt)
539        except EOFError: # raised by self.rawq_getchar()
540            self.iacseq = '' # Reset on EOF
541            self.sb = 0
542            pass
543        self.cookedq = self.cookedq + buf[0]
544        self.sbdataq = self.sbdataq + buf[1]
545
546    def rawq_getchar(self):
547        """Get next char from raw queue.
548
549        Block if no data is immediately available.  Raise EOFError
550        when connection is closed.
551
552        """
553        if not self.rawq:
554            self.fill_rawq()
555            if self.eof:
556                raise EOFError
557        c = self.rawq[self.irawq]
558        self.irawq = self.irawq + 1
559        if self.irawq >= len(self.rawq):
560            self.rawq = ''
561            self.irawq = 0
562        return c
563
564    def fill_rawq(self):
565        """Fill raw queue from exactly one recv() system call.
566
567        Block if no data is immediately available.  Set self.eof when
568        connection is closed.
569
570        """
571        if self.irawq >= len(self.rawq):
572            self.rawq = ''
573            self.irawq = 0
574        # The buffer size should be fairly small so as to avoid quadratic
575        # behavior in process_rawq() above
576        buf = self.sock.recv(50)
577        self.msg("recv %r", buf)
578        self.eof = (not buf)
579        self.rawq = self.rawq + buf
580
581    def sock_avail(self):
582        """Test whether data is available on the socket."""
583        return select.select([self], [], [], 0) == ([self], [], [])
584
585    def interact(self):
586        """Interaction function, emulates a very dumb telnet client."""
587        if sys.platform == "win32":
588            self.mt_interact()
589            return
590        while 1:
591            rfd, wfd, xfd = select.select([self, sys.stdin], [], [])
592            if self in rfd:
593                try:
594                    text = self.read_eager()
595                except EOFError:
596                    print '*** Connection closed by remote host ***'
597                    break
598                if text:
599                    sys.stdout.write(text)
600                    sys.stdout.flush()
601            if sys.stdin in rfd:
602                line = sys.stdin.readline()
603                if not line:
604                    break
605                self.write(line)
606
607    def mt_interact(self):
608        """Multithreaded version of interact()."""
609        import thread
610        thread.start_new_thread(self.listener, ())
611        while 1:
612            line = sys.stdin.readline()
613            if not line:
614                break
615            self.write(line)
616
617    def listener(self):
618        """Helper for mt_interact() -- this executes in the other thread."""
619        while 1:
620            try:
621                data = self.read_eager()
622            except EOFError:
623                print '*** Connection closed by remote host ***'
624                return
625            if data:
626                sys.stdout.write(data)
627            else:
628                sys.stdout.flush()
629
630    def expect(self, list, timeout=None):
631        """Read until one from a list of a regular expressions matches.
632
633        The first argument is a list of regular expressions, either
634        compiled (re.RegexObject instances) or uncompiled (strings).
635        The optional second argument is a timeout, in seconds; default
636        is no timeout.
637
638        Return a tuple of three items: the index in the list of the
639        first regular expression that matches; the match object
640        returned; and the text read up till and including the match.
641
642        If EOF is read and no text was read, raise EOFError.
643        Otherwise, when nothing matches, return (-1, None, text) where
644        text is the text received so far (may be the empty string if a
645        timeout happened).
646
647        If a regular expression ends with a greedy match (e.g. '.*')
648        or if more than one expression can match the same input, the
649        results are undeterministic, and may depend on the I/O timing.
650
651        """
652        if self._has_poll:
653            return self._expect_with_poll(list, timeout)
654        else:
655            return self._expect_with_select(list, timeout)
656
657    def _expect_with_poll(self, expect_list, timeout=None):
658        """Read until one from a list of a regular expressions matches.
659
660        This method uses select.poll() to implement the timeout.
661        """
662        re = None
663        expect_list = expect_list[:]
664        indices = range(len(expect_list))
665        for i in indices:
666            if not hasattr(expect_list[i], "search"):
667                if not re: import re
668                expect_list[i] = re.compile(expect_list[i])
669        call_timeout = timeout
670        if timeout is not None:
671            from time import time
672            time_start = time()
673        self.process_rawq()
674        m = None
675        for i in indices:
676            m = expect_list[i].search(self.cookedq)
677            if m:
678                e = m.end()
679                text = self.cookedq[:e]
680                self.cookedq = self.cookedq[e:]
681                break
682        if not m:
683            poller = select.poll()
684            poll_in_or_priority_flags = select.POLLIN | select.POLLPRI
685            poller.register(self, poll_in_or_priority_flags)
686            while not m and not self.eof:
687                try:
688                    ready = poller.poll(None if timeout is None
689                                        else 1000 * call_timeout)
690                except select.error as e:
691                    if e.errno == errno.EINTR:
692                        if timeout is not None:
693                            elapsed = time() - time_start
694                            call_timeout = timeout-elapsed
695                        continue
696                    raise
697                for fd, mode in ready:
698                    if mode & poll_in_or_priority_flags:
699                        self.fill_rawq()
700                        self.process_rawq()
701                        for i in indices:
702                            m = expect_list[i].search(self.cookedq)
703                            if m:
704                                e = m.end()
705                                text = self.cookedq[:e]
706                                self.cookedq = self.cookedq[e:]
707                                break
708                if timeout is not None:
709                    elapsed = time() - time_start
710                    if elapsed >= timeout:
711                        break
712                    call_timeout = timeout-elapsed
713            poller.unregister(self)
714        if m:
715            return (i, m, text)
716        text = self.read_very_lazy()
717        if not text and self.eof:
718            raise EOFError
719        return (-1, None, text)
720
721    def _expect_with_select(self, list, timeout=None):
722        """Read until one from a list of a regular expressions matches.
723
724        The timeout is implemented using select.select().
725        """
726        re = None
727        list = list[:]
728        indices = range(len(list))
729        for i in indices:
730            if not hasattr(list[i], "search"):
731                if not re: import re
732                list[i] = re.compile(list[i])
733        if timeout is not None:
734            from time import time
735            time_start = time()
736        while 1:
737            self.process_rawq()
738            for i in indices:
739                m = list[i].search(self.cookedq)
740                if m:
741                    e = m.end()
742                    text = self.cookedq[:e]
743                    self.cookedq = self.cookedq[e:]
744                    return (i, m, text)
745            if self.eof:
746                break
747            if timeout is not None:
748                elapsed = time() - time_start
749                if elapsed >= timeout:
750                    break
751                s_args = ([self.fileno()], [], [], timeout-elapsed)
752                r, w, x = select.select(*s_args)
753                if not r:
754                    break
755            self.fill_rawq()
756        text = self.read_very_lazy()
757        if not text and self.eof:
758            raise EOFError
759        return (-1, None, text)
760
761
762def test():
763    """Test program for telnetlib.
764
765    Usage: python telnetlib.py [-d] ... [host [port]]
766
767    Default host is localhost; default port is 23.
768
769    """
770    debuglevel = 0
771    while sys.argv[1:] and sys.argv[1] == '-d':
772        debuglevel = debuglevel+1
773        del sys.argv[1]
774    host = 'localhost'
775    if sys.argv[1:]:
776        host = sys.argv[1]
777    port = 0
778    if sys.argv[2:]:
779        portstr = sys.argv[2]
780        try:
781            port = int(portstr)
782        except ValueError:
783            port = socket.getservbyname(portstr, 'tcp')
784    tn = Telnet()
785    tn.set_debuglevel(debuglevel)
786    tn.open(host, port, timeout=0.5)
787    tn.interact()
788    tn.close()
789
790if __name__ == '__main__':
791    test()
Note: See TracBrowser for help on using the repository browser.