blob: 6d8b9693882ed5f8c9e595934ca76b13373aec33 [file] [log] [blame]
Tim Hammerquist545ba4e2017-12-12 02:36:17 +00001# COPYRIGHT LINE: FIXME
2
3"""
4dbsign.shell
5
6shell routines for debugsign
7"""
8
9from __future__ import print_function
10
11import os
12from subprocess import PIPE, Popen
13
14import dbsign.logger
15
16
17log = dbsign.logger.get_logger(__name__)
18
19
20class ShellCommand(object):
21 """
22 Represents the result of a shell command
23 """
24 def __init__(self, args, code, stdout, stderr):
25 # type: (list[str], int, str, str) -> ()
26 self.data = {
27 'args': args,
28 'code': code,
29 'stdout': stdout,
30 'stderr': stderr,
31 }
32
33 def __eq__(self, rhs): # type: (ShellCommand) -> bool
34 return self.data == rhs.data
35
36 def __getattr__(self, attr): # type: (str) -> T
37 if attr in self.data:
38 return self.data[attr]
39 raise AttributeError(attr)
40
41 def __nonzero__(self): # type: () -> bool
42 return self.code == 0
43
44 def __repr__(self): # type: () -> str
45 repr_fmt = "{0}(args={1.args!r}, code={1.code!r},"
46 repr_fmt += " stdout={1.stdout!r}, stderr={1.stderr!r})"
47 return repr_fmt.format(self.__class__.__name__, self)
48
49
50def __run(args, stdin=None): # type: (list[str], str) -> ShellCommand
51 """internal function to run shell commands"""
52 try:
53 p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
54 stdout, stderr = p.communicate(input=stdin)
55 except OSError as os_err:
56 log.debug('Unable to execute command: %s: %s', args, os_err)
57 raise
58
59 cmd = ShellCommand(args, code=p.returncode, stdout=stdout, stderr=stderr)
60 log.debug(cmd)
61 return cmd
62
63
64def run(args, stdin=None): # type: (list[str]) -> ShellCommand
65 """Run a regular (non-sudo) command"""
66 log.debug("run(args=%s)", repr(args))
67
68 if os.path.basename(args[0]).startswith('su'):
69 log.info('run() called with illegal command `%s`', args)
70 raise RuntimeError('Unauthorized use of run; use sudo_run')
71
72 return __run(args, stdin)
73
74
75def sudo_run(args, stdin=None): # type: (list[str]) -> ShellCommand
76 """Run a command with root privileges using sudo"""
77 log.debug("sudo_run(args=%s)", repr(args))
78
79 args.insert(0, 'sudo')
80
81 return __run(args, stdin)