From edc4d8644e9bf5ac6af02a3ae28e3927337921a9 Mon Sep 17 00:00:00 2001 From: brian c Date: Mon, 12 Jul 2010 16:42:03 -0400 Subject: [PATCH] Unix: various enhancements to the ping command: Fixed bug in 100% packet loss response. Errors from ping are now sent to irc.error(). Added packet count, interval, ttl, and wait options. Added additional test cases. Also, Enabled threading for Unix plugin, and for wtf, spell, and ping commands. Signed-off-by: Daniel Folkinshteyn --- plugins/Unix/plugin.py | 52 ++++++++++++++++++++++++++++-------------- plugins/Unix/test.py | 22 +++++++++++++++--- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/plugins/Unix/plugin.py b/plugins/Unix/plugin.py index 7396da95c..2dd5ba7b3 100644 --- a/plugins/Unix/plugin.py +++ b/plugins/Unix/plugin.py @@ -66,6 +66,7 @@ def pipeReadline(fd, timeout=2): raise TimeoutError class Unix(callbacks.Plugin): + threaded = True def errno(self, irc, msg, args, s): """ @@ -181,7 +182,7 @@ class Unix(callbacks.Plugin): else: resp = 'Something unexpected was seen in the [ai]spell output.' irc.reply(resp) - spell = wrap(spell, ['something']) + spell = thread(wrap(spell, ['something'])) def fortune(self, irc, msg, args): """takes no arguments @@ -247,11 +248,14 @@ class Unix(callbacks.Plugin): 'on this system, reconfigure the ' 'supybot.plugins.Unix.wtf.command configuration ' 'variable appropriately.') - wtf = wrap(wtf, [optional(('literal', ['is'])), 'something']) + wtf = thread(wrap(wtf, [optional(('literal', ['is'])), 'something'])) - def ping(self, irc, msg, args, host): - """ - Sends an ICMP echo request to the specified host + def ping(self, irc, msg, args, optlist, host): + """[--c ] [--i ] [--t ] [--W ] + Sends an ICMP echo request to the specified host. + The arguments correspond with those listed in ping(8). --c is + limited to 10 packets or less (default is 5). --i is limited to 5 + or less. --W is limited to 10 or less. """ pingCmd = self.registryValue('ping.command') if not pingCmd: @@ -263,26 +267,40 @@ class Unix(callbacks.Plugin): try: host = host.group(0) except AttributeError: pass + args = [pingCmd] + for opt, val in optlist: + if opt == 'c' and val > 10: val = 10 + if opt == 'i' and val > 5: val = 5 + if opt == 'W' and val > 10: val = 10 + args.append('-%s' % opt) + args.append(str(val)) + if '-c' not in args: + args.append('-c') + args.append('5') + args.append(host) try: - inst = subprocess.Popen([pingCmd,'-c','1', host], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=file(os.devnull)) + inst = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=file(os.devnull)) except OSError, e: irc.error('It seems the configured ping command was ' 'not available (%s).' % e, Raise=True) - result = inst.communicate() - if result[1]: # stderr - irc.reply(' '.join(result[1].split())) + irc.error(' '.join(result[1].split())) else: response = result[0].split("\n"); - irc.reply(' '.join(response[1].split()[3:5]).split(':')[0] - + ': ' + ' '.join(response[-3:])) - - _hostExpr = re.compile(r'^[a-z0-9][a-z0-9\.-]*$', re.I) - ping = wrap(ping, [first('ip', ('matches', _hostExpr, 'Invalid hostname'))]) + if response[1]: + irc.reply(' '.join(response[1].split()[3:5]).split(':')[0] + + ': ' + ' '.join(response[-3:])) + else: + irc.reply(' '.join(response[0].split()[1:3]) + + ': ' + ' '.join(response[-3:])) + + _hostExpr = re.compile(r'^[a-z0-9][a-z0-9\.-]*[a-z0-9]$', re.I) + ping = thread(wrap(ping, [getopts({'c':'positiveInt','i':'float', + 't':'positiveInt','W':'positiveInt'}), + first('ip', ('matches', _hostExpr, 'Invalid hostname'))])) Class = Unix # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/plugins/Unix/test.py b/plugins/Unix/test.py index 8f67ce351..86d73db50 100644 --- a/plugins/Unix/test.py +++ b/plugins/Unix/test.py @@ -66,9 +66,25 @@ if os.name == 'posix': if utils.findBinaryInPath('ping') is not None: def testPing(self): - self.assertNotError('unix ping localhost') + self.assertNotError('unix ping 127.0.0.1') self.assertError('unix ping') - - + self.assertError('unix ping -localhost') + self.assertError('unix ping local%host') + def testPingCount(self): + self.assertNotError('unix ping --c 1 127.0.0.1') + self.assertError('unix ping --c a 127.0.0.1') + self.assertRegexp('unix ping --c 11 127.0.0.1','10 packets') + self.assertRegexp('unix ping 127.0.0.1','5 packets') + def testPingInterval(self): + self.assertNotError('unix ping --i 1 --c 1 127.0.0.1') + self.assertError('unix ping --i a --c 1 127.0.0.1') + # Super-user privileged interval setting + self.assertError('unix ping --i 0.1 --c 1 127.0.0.1') + def testPingTtl(self): + self.assertNotError('unix ping --t 64 --c 1 127.0.0.1') + self.assertError('unix ping --t a --c 1 127.0.0.1') + def testPingWait(self): + self.assertNotError('unix ping --W 1 --c 1 127.0.0.1') + self.assertError('unix ping --W a --c 1 127.0.0.1') # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: