blob: 6d8b9693882ed5f8c9e595934ca76b13373aec33 [file] [log] [blame]
# COPYRIGHT LINE: FIXME
"""
dbsign.shell
shell routines for debugsign
"""
from __future__ import print_function
import os
from subprocess import PIPE, Popen
import dbsign.logger
log = dbsign.logger.get_logger(__name__)
class ShellCommand(object):
"""
Represents the result of a shell command
"""
def __init__(self, args, code, stdout, stderr):
# type: (list[str], int, str, str) -> ()
self.data = {
'args': args,
'code': code,
'stdout': stdout,
'stderr': stderr,
}
def __eq__(self, rhs): # type: (ShellCommand) -> bool
return self.data == rhs.data
def __getattr__(self, attr): # type: (str) -> T
if attr in self.data:
return self.data[attr]
raise AttributeError(attr)
def __nonzero__(self): # type: () -> bool
return self.code == 0
def __repr__(self): # type: () -> str
repr_fmt = "{0}(args={1.args!r}, code={1.code!r},"
repr_fmt += " stdout={1.stdout!r}, stderr={1.stderr!r})"
return repr_fmt.format(self.__class__.__name__, self)
def __run(args, stdin=None): # type: (list[str], str) -> ShellCommand
"""internal function to run shell commands"""
try:
p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate(input=stdin)
except OSError as os_err:
log.debug('Unable to execute command: %s: %s', args, os_err)
raise
cmd = ShellCommand(args, code=p.returncode, stdout=stdout, stderr=stderr)
log.debug(cmd)
return cmd
def run(args, stdin=None): # type: (list[str]) -> ShellCommand
"""Run a regular (non-sudo) command"""
log.debug("run(args=%s)", repr(args))
if os.path.basename(args[0]).startswith('su'):
log.info('run() called with illegal command `%s`', args)
raise RuntimeError('Unauthorized use of run; use sudo_run')
return __run(args, stdin)
def sudo_run(args, stdin=None): # type: (list[str]) -> ShellCommand
"""Run a command with root privileges using sudo"""
log.debug("sudo_run(args=%s)", repr(args))
args.insert(0, 'sudo')
return __run(args, stdin)