diff --git a/plugins/Unix/plugin.py b/plugins/Unix/plugin.py index 28b79989d..92c249747 100644 --- a/plugins/Unix/plugin.py +++ b/plugins/Unix/plugin.py @@ -38,6 +38,7 @@ import random import select import struct import subprocess +import shlex import supybot.utils as utils from supybot.commands import * @@ -314,5 +315,31 @@ class Unix(callbacks.Plugin): 't':'positiveInt','W':'positiveInt'}), first('ip', ('matches', _hostExpr, 'Invalid hostname'))])) + def call(self, irc, msg, args, text): + """ + Calls any command available on the system, and returns its output. + Requires owner capability. + Note that being restricted to owner, this command does not do any + sanity checking on input/output. So it is up to you to make sure + you don't run anything that will spamify your channel or that + will bring your machine to its knees. + """ + args = shlex.split(text) + try: + inst = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=file(os.devnull)) + except OSError, e: + irc.error('It seems the requested command was ' + 'not available (%s).' % e, Raise=True) + result = inst.communicate() + if result[1]: # stderr + irc.error(' '.join(result[1].split())) + if result[0]: # stdout + response = result[0].split("\n"); + response = [l for l in response if l] + irc.replies(response) + call = thread(wrap(call, ["owner", "text"])) + Class = Unix # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/plugins/Unix/test.py b/plugins/Unix/test.py index e46dcb7e7..42b8d4108 100644 --- a/plugins/Unix/test.py +++ b/plugins/Unix/test.py @@ -88,4 +88,8 @@ if os.name == 'posix': self.assertNotError('unix ping --W 1 --c 1 127.0.0.1') self.assertError('unix ping --W a --c 1 127.0.0.1') + def testCall(self): + self.assertNotError('unix call /bin/ping -c 1 localhost') + self.assertRegexp('unix call /bin/ping -c 1 localhost', 'ping statistics') + self.assertError('unix call /usr/bin/nosuchcommandaoeuaoeu') # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: