ยปCore Development>Code coverage>Lib/telnetlib.py

Python code coverage for Lib/telnetlib.py

#countcontent
1n/ar"""TELNET client class.
2n/a
3n/aBased on RFC 854: TELNET Protocol Specification, by J. Postel and
4n/aJ. Reynolds
5n/a
6n/aExample:
7n/a
8n/a>>> from telnetlib import Telnet
9n/a>>> tn = Telnet('www.python.org', 79) # connect to finger port
10n/a>>> tn.write(b'guido\r\n')
11n/a>>> print(tn.read_all())
12n/aLogin Name TTY Idle When Where
13n/aguido Guido van Rossum pts/2 <Dec 2 11:10> snag.cnri.reston..
14n/a
15n/a>>>
16n/a
17n/aNote that read_all() won't read until eof -- it just reads some data
18n/a-- but it guarantees to read at least one byte unless EOF is hit.
19n/a
20n/aIt is possible to pass a Telnet object to a selector in order to wait until
21n/amore data is available. Note that in this case, read_eager() may return b''
22n/aeven if there was data on the socket, because the protocol negotiation may have
23n/aeaten the data. This is why EOFError is needed in some cases to distinguish
24n/abetween "no data" and "connection closed" (since the socket also appears ready
25n/afor reading when it is closed).
26n/a
27n/aTo do:
28n/a- option negotiation
29n/a- timeout should be intrinsic to the connection object instead of an
30n/a option on one of the read calls only
31n/a
32n/a"""
33n/a
34n/a
35n/a# Imported modules
36n/aimport sys
37n/aimport socket
38n/aimport selectors
39n/afrom time import monotonic as _time
40n/a
41n/a__all__ = ["Telnet"]
42n/a
43n/a# Tunable parameters
44n/aDEBUGLEVEL = 0
45n/a
46n/a# Telnet protocol defaults
47n/aTELNET_PORT = 23
48n/a
49n/a# Telnet protocol characters (don't change)
50n/aIAC = bytes([255]) # "Interpret As Command"
51n/aDONT = bytes([254])
52n/aDO = bytes([253])
53n/aWONT = bytes([252])
54n/aWILL = bytes([251])
55n/atheNULL = bytes([0])
56n/a
57n/aSE = bytes([240]) # Subnegotiation End
58n/aNOP = bytes([241]) # No Operation
59n/aDM = bytes([242]) # Data Mark
60n/aBRK = bytes([243]) # Break
61n/aIP = bytes([244]) # Interrupt process
62n/aAO = bytes([245]) # Abort output
63n/aAYT = bytes([246]) # Are You There
64n/aEC = bytes([247]) # Erase Character
65n/aEL = bytes([248]) # Erase Line
66n/aGA = bytes([249]) # Go Ahead
67n/aSB = bytes([250]) # Subnegotiation Begin
68n/a
69n/a
70n/a# Telnet protocol options code (don't change)
71n/a# These ones all come from arpa/telnet.h
72n/aBINARY = bytes([0]) # 8-bit data path
73n/aECHO = bytes([1]) # echo
74n/aRCP = bytes([2]) # prepare to reconnect
75n/aSGA = bytes([3]) # suppress go ahead
76n/aNAMS = bytes([4]) # approximate message size
77n/aSTATUS = bytes([5]) # give status
78n/aTM = bytes([6]) # timing mark
79n/aRCTE = bytes([7]) # remote controlled transmission and echo
80n/aNAOL = bytes([8]) # negotiate about output line width
81n/aNAOP = bytes([9]) # negotiate about output page size
82n/aNAOCRD = bytes([10]) # negotiate about CR disposition
83n/aNAOHTS = bytes([11]) # negotiate about horizontal tabstops
84n/aNAOHTD = bytes([12]) # negotiate about horizontal tab disposition
85n/aNAOFFD = bytes([13]) # negotiate about formfeed disposition
86n/aNAOVTS = bytes([14]) # negotiate about vertical tab stops
87n/aNAOVTD = bytes([15]) # negotiate about vertical tab disposition
88n/aNAOLFD = bytes([16]) # negotiate about output LF disposition
89n/aXASCII = bytes([17]) # extended ascii character set
90n/aLOGOUT = bytes([18]) # force logout
91n/aBM = bytes([19]) # byte macro
92n/aDET = bytes([20]) # data entry terminal
93n/aSUPDUP = bytes([21]) # supdup protocol
94n/aSUPDUPOUTPUT = bytes([22]) # supdup output
95n/aSNDLOC = bytes([23]) # send location
96n/aTTYPE = bytes([24]) # terminal type
97n/aEOR = bytes([25]) # end or record
98n/aTUID = bytes([26]) # TACACS user identification
99n/aOUTMRK = bytes([27]) # output marking
100n/aTTYLOC = bytes([28]) # terminal location number
101n/aVT3270REGIME = bytes([29]) # 3270 regime
102n/aX3PAD = bytes([30]) # X.3 PAD
103n/aNAWS = bytes([31]) # window size
104n/aTSPEED = bytes([32]) # terminal speed
105n/aLFLOW = bytes([33]) # remote flow control
106n/aLINEMODE = bytes([34]) # Linemode option
107n/aXDISPLOC = bytes([35]) # X Display Location
108n/aOLD_ENVIRON = bytes([36]) # Old - Environment variables
109n/aAUTHENTICATION = bytes([37]) # Authenticate
110n/aENCRYPT = bytes([38]) # Encryption option
111n/aNEW_ENVIRON = bytes([39]) # New - Environment variables
112n/a# the following ones come from
113n/a# http://www.iana.org/assignments/telnet-options
114n/a# Unfortunately, that document does not assign identifiers
115n/a# to all of them, so we are making them up
116n/aTN3270E = bytes([40]) # TN3270E
117n/aXAUTH = bytes([41]) # XAUTH
118n/aCHARSET = bytes([42]) # CHARSET
119n/aRSP = bytes([43]) # Telnet Remote Serial Port
120n/aCOM_PORT_OPTION = bytes([44]) # Com Port Control Option
121n/aSUPPRESS_LOCAL_ECHO = bytes([45]) # Telnet Suppress Local Echo
122n/aTLS = bytes([46]) # Telnet Start TLS
123n/aKERMIT = bytes([47]) # KERMIT
124n/aSEND_URL = bytes([48]) # SEND-URL
125n/aFORWARD_X = bytes([49]) # FORWARD_X
126n/aPRAGMA_LOGON = bytes([138]) # TELOPT PRAGMA LOGON
127n/aSSPI_LOGON = bytes([139]) # TELOPT SSPI LOGON
128n/aPRAGMA_HEARTBEAT = bytes([140]) # TELOPT PRAGMA HEARTBEAT
129n/aEXOPL = bytes([255]) # Extended-Options-List
130n/aNOOPT = bytes([0])
131n/a
132n/a
133n/a# poll/select have the advantage of not requiring any extra file descriptor,
134n/a# contrarily to epoll/kqueue (also, they require a single syscall).
135n/aif hasattr(selectors, 'PollSelector'):
136n/a _TelnetSelector = selectors.PollSelector
137n/aelse:
138n/a _TelnetSelector = selectors.SelectSelector
139n/a
140n/a
141n/aclass Telnet:
142n/a
143n/a """Telnet interface class.
144n/a
145n/a An instance of this class represents a connection to a telnet
146n/a server. The instance is initially not connected; the open()
147n/a method must be used to establish a connection. Alternatively, the
148n/a host name and optional port number can be passed to the
149n/a constructor, too.
150n/a
151n/a Don't try to reopen an already connected instance.
152n/a
153n/a This class has many read_*() methods. Note that some of them
154n/a raise EOFError when the end of the connection is read, because
155n/a they can return an empty string for other reasons. See the
156n/a individual doc strings.
157n/a
158n/a read_until(expected, [timeout])
159n/a Read until the expected string has been seen, or a timeout is
160n/a hit (default is no timeout); may block.
161n/a
162n/a read_all()
163n/a Read all data until EOF; may block.
164n/a
165n/a read_some()
166n/a Read at least one byte or EOF; may block.
167n/a
168n/a read_very_eager()
169n/a Read all data available already queued or on the socket,
170n/a without blocking.
171n/a
172n/a read_eager()
173n/a Read either data already queued or some data available on the
174n/a socket, without blocking.
175n/a
176n/a read_lazy()
177n/a Read all data in the raw queue (processing it first), without
178n/a doing any socket I/O.
179n/a
180n/a read_very_lazy()
181n/a Reads all data in the cooked queue, without doing any socket
182n/a I/O.
183n/a
184n/a read_sb_data()
185n/a Reads available data between SB ... SE sequence. Don't block.
186n/a
187n/a set_option_negotiation_callback(callback)
188n/a Each time a telnet option is read on the input flow, this callback
189n/a (if set) is called with the following parameters :
190n/a callback(telnet socket, command, option)
191n/a option will be chr(0) when there is no option.
192n/a No other action is done afterwards by telnetlib.
193n/a
194n/a """
195n/a
196n/a def __init__(self, host=None, port=0,
197n/a timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
198n/a """Constructor.
199n/a
200n/a When called without arguments, create an unconnected instance.
201n/a With a hostname argument, it connects the instance; port number
202n/a and timeout are optional.
203n/a """
204n/a self.debuglevel = DEBUGLEVEL
205n/a self.host = host
206n/a self.port = port
207n/a self.timeout = timeout
208n/a self.sock = None
209n/a self.rawq = b''
210n/a self.irawq = 0
211n/a self.cookedq = b''
212n/a self.eof = 0
213n/a self.iacseq = b'' # Buffer for IAC sequence.
214n/a self.sb = 0 # flag for SB and SE sequence.
215n/a self.sbdataq = b''
216n/a self.option_callback = None
217n/a if host is not None:
218n/a self.open(host, port, timeout)
219n/a
220n/a def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
221n/a """Connect to a host.
222n/a
223n/a The optional second argument is the port number, which
224n/a defaults to the standard telnet port (23).
225n/a
226n/a Don't try to reopen an already connected instance.
227n/a """
228n/a self.eof = 0
229n/a if not port:
230n/a port = TELNET_PORT
231n/a self.host = host
232n/a self.port = port
233n/a self.timeout = timeout
234n/a self.sock = socket.create_connection((host, port), timeout)
235n/a
236n/a def __del__(self):
237n/a """Destructor -- close the connection."""
238n/a self.close()
239n/a
240n/a def msg(self, msg, *args):
241n/a """Print a debug message, when the debug level is > 0.
242n/a
243n/a If extra arguments are present, they are substituted in the
244n/a message using the standard string formatting operator.
245n/a
246n/a """
247n/a if self.debuglevel > 0:
248n/a print('Telnet(%s,%s):' % (self.host, self.port), end=' ')
249n/a if args:
250n/a print(msg % args)
251n/a else:
252n/a print(msg)
253n/a
254n/a def set_debuglevel(self, debuglevel):
255n/a """Set the debug level.
256n/a
257n/a The higher it is, the more debug output you get (on sys.stdout).
258n/a
259n/a """
260n/a self.debuglevel = debuglevel
261n/a
262n/a def close(self):
263n/a """Close the connection."""
264n/a sock = self.sock
265n/a self.sock = None
266n/a self.eof = True
267n/a self.iacseq = b''
268n/a self.sb = 0
269n/a if sock:
270n/a sock.close()
271n/a
272n/a def get_socket(self):
273n/a """Return the socket object used internally."""
274n/a return self.sock
275n/a
276n/a def fileno(self):
277n/a """Return the fileno() of the socket object used internally."""
278n/a return self.sock.fileno()
279n/a
280n/a def write(self, buffer):
281n/a """Write a string to the socket, doubling any IAC characters.
282n/a
283n/a Can block if the connection is blocked. May raise
284n/a OSError if the connection is closed.
285n/a
286n/a """
287n/a if IAC in buffer:
288n/a buffer = buffer.replace(IAC, IAC+IAC)
289n/a self.msg("send %r", buffer)
290n/a self.sock.sendall(buffer)
291n/a
292n/a def read_until(self, match, timeout=None):
293n/a """Read until a given string is encountered or until timeout.
294n/a
295n/a When no match is found, return whatever is available instead,
296n/a possibly the empty string. Raise EOFError if the connection
297n/a is closed and no cooked data is available.
298n/a
299n/a """
300n/a n = len(match)
301n/a self.process_rawq()
302n/a i = self.cookedq.find(match)
303n/a if i >= 0:
304n/a i = i+n
305n/a buf = self.cookedq[:i]
306n/a self.cookedq = self.cookedq[i:]
307n/a return buf
308n/a if timeout is not None:
309n/a deadline = _time() + timeout
310n/a with _TelnetSelector() as selector:
311n/a selector.register(self, selectors.EVENT_READ)
312n/a while not self.eof:
313n/a if selector.select(timeout):
314n/a i = max(0, len(self.cookedq)-n)
315n/a self.fill_rawq()
316n/a self.process_rawq()
317n/a i = self.cookedq.find(match, i)
318n/a if i >= 0:
319n/a i = i+n
320n/a buf = self.cookedq[:i]
321n/a self.cookedq = self.cookedq[i:]
322n/a return buf
323n/a if timeout is not None:
324n/a timeout = deadline - _time()
325n/a if timeout < 0:
326n/a break
327n/a return self.read_very_lazy()
328n/a
329n/a def read_all(self):
330n/a """Read all data until EOF; block until connection closed."""
331n/a self.process_rawq()
332n/a while not self.eof:
333n/a self.fill_rawq()
334n/a self.process_rawq()
335n/a buf = self.cookedq
336n/a self.cookedq = b''
337n/a return buf
338n/a
339n/a def read_some(self):
340n/a """Read at least one byte of cooked data unless EOF is hit.
341n/a
342n/a Return b'' if EOF is hit. Block if no data is immediately
343n/a available.
344n/a
345n/a """
346n/a self.process_rawq()
347n/a while not self.cookedq and not self.eof:
348n/a self.fill_rawq()
349n/a self.process_rawq()
350n/a buf = self.cookedq
351n/a self.cookedq = b''
352n/a return buf
353n/a
354n/a def read_very_eager(self):
355n/a """Read everything that's possible without blocking in I/O (eager).
356n/a
357n/a Raise EOFError if connection closed and no cooked data
358n/a available. Return b'' if no cooked data available otherwise.
359n/a Don't block unless in the midst of an IAC sequence.
360n/a
361n/a """
362n/a self.process_rawq()
363n/a while not self.eof and self.sock_avail():
364n/a self.fill_rawq()
365n/a self.process_rawq()
366n/a return self.read_very_lazy()
367n/a
368n/a def read_eager(self):
369n/a """Read readily available data.
370n/a
371n/a Raise EOFError if connection closed and no cooked data
372n/a available. Return b'' if no cooked data available otherwise.
373n/a Don't block unless in the midst of an IAC sequence.
374n/a
375n/a """
376n/a self.process_rawq()
377n/a while not self.cookedq and not self.eof and self.sock_avail():
378n/a self.fill_rawq()
379n/a self.process_rawq()
380n/a return self.read_very_lazy()
381n/a
382n/a def read_lazy(self):
383n/a """Process and return data that's already in the queues (lazy).
384n/a
385n/a Raise EOFError if connection closed and no data available.
386n/a Return b'' if no cooked data available otherwise. Don't block
387n/a unless in the midst of an IAC sequence.
388n/a
389n/a """
390n/a self.process_rawq()
391n/a return self.read_very_lazy()
392n/a
393n/a def read_very_lazy(self):
394n/a """Return any data available in the cooked queue (very lazy).
395n/a
396n/a Raise EOFError if connection closed and no data available.
397n/a Return b'' if no cooked data available otherwise. Don't block.
398n/a
399n/a """
400n/a buf = self.cookedq
401n/a self.cookedq = b''
402n/a if not buf and self.eof and not self.rawq:
403n/a raise EOFError('telnet connection closed')
404n/a return buf
405n/a
406n/a def read_sb_data(self):
407n/a """Return any data available in the SB ... SE queue.
408n/a
409n/a Return b'' if no SB ... SE available. Should only be called
410n/a after seeing a SB or SE command. When a new SB command is
411n/a found, old unread SB data will be discarded. Don't block.
412n/a
413n/a """
414n/a buf = self.sbdataq
415n/a self.sbdataq = b''
416n/a return buf
417n/a
418n/a def set_option_negotiation_callback(self, callback):
419n/a """Provide a callback function called after each receipt of a telnet option."""
420n/a self.option_callback = callback
421n/a
422n/a def process_rawq(self):
423n/a """Transfer from raw queue to cooked queue.
424n/a
425n/a Set self.eof when connection is closed. Don't block unless in
426n/a the midst of an IAC sequence.
427n/a
428n/a """
429n/a buf = [b'', b'']
430n/a try:
431n/a while self.rawq:
432n/a c = self.rawq_getchar()
433n/a if not self.iacseq:
434n/a if c == theNULL:
435n/a continue
436n/a if c == b"\021":
437n/a continue
438n/a if c != IAC:
439n/a buf[self.sb] = buf[self.sb] + c
440n/a continue
441n/a else:
442n/a self.iacseq += c
443n/a elif len(self.iacseq) == 1:
444n/a # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
445n/a if c in (DO, DONT, WILL, WONT):
446n/a self.iacseq += c
447n/a continue
448n/a
449n/a self.iacseq = b''
450n/a if c == IAC:
451n/a buf[self.sb] = buf[self.sb] + c
452n/a else:
453n/a if c == SB: # SB ... SE start.
454n/a self.sb = 1
455n/a self.sbdataq = b''
456n/a elif c == SE:
457n/a self.sb = 0
458n/a self.sbdataq = self.sbdataq + buf[1]
459n/a buf[1] = b''
460n/a if self.option_callback:
461n/a # Callback is supposed to look into
462n/a # the sbdataq
463n/a self.option_callback(self.sock, c, NOOPT)
464n/a else:
465n/a # We can't offer automatic processing of
466n/a # suboptions. Alas, we should not get any
467n/a # unless we did a WILL/DO before.
468n/a self.msg('IAC %d not recognized' % ord(c))
469n/a elif len(self.iacseq) == 2:
470n/a cmd = self.iacseq[1:2]
471n/a self.iacseq = b''
472n/a opt = c
473n/a if cmd in (DO, DONT):
474n/a self.msg('IAC %s %d',
475n/a cmd == DO and 'DO' or 'DONT', ord(opt))
476n/a if self.option_callback:
477n/a self.option_callback(self.sock, cmd, opt)
478n/a else:
479n/a self.sock.sendall(IAC + WONT + opt)
480n/a elif cmd in (WILL, WONT):
481n/a self.msg('IAC %s %d',
482n/a cmd == WILL and 'WILL' or 'WONT', ord(opt))
483n/a if self.option_callback:
484n/a self.option_callback(self.sock, cmd, opt)
485n/a else:
486n/a self.sock.sendall(IAC + DONT + opt)
487n/a except EOFError: # raised by self.rawq_getchar()
488n/a self.iacseq = b'' # Reset on EOF
489n/a self.sb = 0
490n/a pass
491n/a self.cookedq = self.cookedq + buf[0]
492n/a self.sbdataq = self.sbdataq + buf[1]
493n/a
494n/a def rawq_getchar(self):
495n/a """Get next char from raw queue.
496n/a
497n/a Block if no data is immediately available. Raise EOFError
498n/a when connection is closed.
499n/a
500n/a """
501n/a if not self.rawq:
502n/a self.fill_rawq()
503n/a if self.eof:
504n/a raise EOFError
505n/a c = self.rawq[self.irawq:self.irawq+1]
506n/a self.irawq = self.irawq + 1
507n/a if self.irawq >= len(self.rawq):
508n/a self.rawq = b''
509n/a self.irawq = 0
510n/a return c
511n/a
512n/a def fill_rawq(self):
513n/a """Fill raw queue from exactly one recv() system call.
514n/a
515n/a Block if no data is immediately available. Set self.eof when
516n/a connection is closed.
517n/a
518n/a """
519n/a if self.irawq >= len(self.rawq):
520n/a self.rawq = b''
521n/a self.irawq = 0
522n/a # The buffer size should be fairly small so as to avoid quadratic
523n/a # behavior in process_rawq() above
524n/a buf = self.sock.recv(50)
525n/a self.msg("recv %r", buf)
526n/a self.eof = (not buf)
527n/a self.rawq = self.rawq + buf
528n/a
529n/a def sock_avail(self):
530n/a """Test whether data is available on the socket."""
531n/a with _TelnetSelector() as selector:
532n/a selector.register(self, selectors.EVENT_READ)
533n/a return bool(selector.select(0))
534n/a
535n/a def interact(self):
536n/a """Interaction function, emulates a very dumb telnet client."""
537n/a if sys.platform == "win32":
538n/a self.mt_interact()
539n/a return
540n/a with _TelnetSelector() as selector:
541n/a selector.register(self, selectors.EVENT_READ)
542n/a selector.register(sys.stdin, selectors.EVENT_READ)
543n/a
544n/a while True:
545n/a for key, events in selector.select():
546n/a if key.fileobj is self:
547n/a try:
548n/a text = self.read_eager()
549n/a except EOFError:
550n/a print('*** Connection closed by remote host ***')
551n/a return
552n/a if text:
553n/a sys.stdout.write(text.decode('ascii'))
554n/a sys.stdout.flush()
555n/a elif key.fileobj is sys.stdin:
556n/a line = sys.stdin.readline().encode('ascii')
557n/a if not line:
558n/a return
559n/a self.write(line)
560n/a
561n/a def mt_interact(self):
562n/a """Multithreaded version of interact()."""
563n/a import _thread
564n/a _thread.start_new_thread(self.listener, ())
565n/a while 1:
566n/a line = sys.stdin.readline()
567n/a if not line:
568n/a break
569n/a self.write(line.encode('ascii'))
570n/a
571n/a def listener(self):
572n/a """Helper for mt_interact() -- this executes in the other thread."""
573n/a while 1:
574n/a try:
575n/a data = self.read_eager()
576n/a except EOFError:
577n/a print('*** Connection closed by remote host ***')
578n/a return
579n/a if data:
580n/a sys.stdout.write(data.decode('ascii'))
581n/a else:
582n/a sys.stdout.flush()
583n/a
584n/a def expect(self, list, timeout=None):
585n/a """Read until one from a list of a regular expressions matches.
586n/a
587n/a The first argument is a list of regular expressions, either
588n/a compiled (re.RegexObject instances) or uncompiled (strings).
589n/a The optional second argument is a timeout, in seconds; default
590n/a is no timeout.
591n/a
592n/a Return a tuple of three items: the index in the list of the
593n/a first regular expression that matches; the match object
594n/a returned; and the text read up till and including the match.
595n/a
596n/a If EOF is read and no text was read, raise EOFError.
597n/a Otherwise, when nothing matches, return (-1, None, text) where
598n/a text is the text received so far (may be the empty string if a
599n/a timeout happened).
600n/a
601n/a If a regular expression ends with a greedy match (e.g. '.*')
602n/a or if more than one expression can match the same input, the
603n/a results are undeterministic, and may depend on the I/O timing.
604n/a
605n/a """
606n/a re = None
607n/a list = list[:]
608n/a indices = range(len(list))
609n/a for i in indices:
610n/a if not hasattr(list[i], "search"):
611n/a if not re: import re
612n/a list[i] = re.compile(list[i])
613n/a if timeout is not None:
614n/a deadline = _time() + timeout
615n/a with _TelnetSelector() as selector:
616n/a selector.register(self, selectors.EVENT_READ)
617n/a while not self.eof:
618n/a self.process_rawq()
619n/a for i in indices:
620n/a m = list[i].search(self.cookedq)
621n/a if m:
622n/a e = m.end()
623n/a text = self.cookedq[:e]
624n/a self.cookedq = self.cookedq[e:]
625n/a return (i, m, text)
626n/a if timeout is not None:
627n/a ready = selector.select(timeout)
628n/a timeout = deadline - _time()
629n/a if not ready:
630n/a if timeout < 0:
631n/a break
632n/a else:
633n/a continue
634n/a self.fill_rawq()
635n/a text = self.read_very_lazy()
636n/a if not text and self.eof:
637n/a raise EOFError
638n/a return (-1, None, text)
639n/a
640n/a def __enter__(self):
641n/a return self
642n/a
643n/a def __exit__(self, type, value, traceback):
644n/a self.close()
645n/a
646n/a
647n/adef test():
648n/a """Test program for telnetlib.
649n/a
650n/a Usage: python telnetlib.py [-d] ... [host [port]]
651n/a
652n/a Default host is localhost; default port is 23.
653n/a
654n/a """
655n/a debuglevel = 0
656n/a while sys.argv[1:] and sys.argv[1] == '-d':
657n/a debuglevel = debuglevel+1
658n/a del sys.argv[1]
659n/a host = 'localhost'
660n/a if sys.argv[1:]:
661n/a host = sys.argv[1]
662n/a port = 0
663n/a if sys.argv[2:]:
664n/a portstr = sys.argv[2]
665n/a try:
666n/a port = int(portstr)
667n/a except ValueError:
668n/a port = socket.getservbyname(portstr, 'tcp')
669n/a with Telnet() as tn:
670n/a tn.set_debuglevel(debuglevel)
671n/a tn.open(host, port, timeout=0.5)
672n/a tn.interact()
673n/a
674n/aif __name__ == '__main__':
675n/a test()