Merge pull request #22 from makermelissa/main

Allow run_command to run as user
This commit is contained in:
Melissa LeBlanc-Williams 2023-09-14 12:35:25 -07:00 committed by GitHub
commit 8503f01a23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 5 deletions

View file

@ -396,4 +396,4 @@ min-public-methods=1
# Exceptions that will emit a warning when being caught. Defaults to # Exceptions that will emit a warning when being caught. Defaults to
# "Exception" # "Exception"
overgeneral-exceptions=Exception overgeneral-exceptions=builtins.Exception

View file

@ -29,6 +29,7 @@ import fcntl
import platform import platform
import fileinput import fileinput
import re import re
import pwd
from datetime import datetime from datetime import datetime
from clint.textui import colored, prompt from clint.textui import colored, prompt
import adafruit_platformdetect import adafruit_platformdetect
@ -65,7 +66,9 @@ class Shell:
) )
return prompt.options(message, options) return prompt.options(message, options)
def run_command(self, cmd, suppress_message=False, return_output=False): def run_command(
self, cmd, suppress_message=False, return_output=False, run_as_user=None
):
""" """
Run a shell command and show the output as it runs Run a shell command and show the output as it runs
""" """
@ -79,13 +82,31 @@ class Shell:
except TypeError: except TypeError:
return "" return ""
# Allow running as a different user if we are root
if self.is_root() and run_as_user is not None:
pw_record = pwd.getpwnam(run_as_user)
env = os.environ.copy()
env["HOME"] = pw_record.pw_dir
env["LOGNAME"] = run_as_user
env["USER"] = pw_record.pw_name
def preexec():
os.setgid(pw_record.pw_gid)
os.setuid(pw_record.pw_uid)
else:
env = None
preexec = None
full_output = "" full_output = ""
with subprocess.Popen( with subprocess.Popen( # pylint: disable=subprocess-popen-preexec-fn
cmd, cmd,
shell=True, shell=True,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True, universal_newlines=True,
env=env,
preexec_fn=preexec,
) as proc: ) as proc:
while proc.poll() is None: while proc.poll() is None:
err = read_stream(proc.stderr) err = read_stream(proc.stderr)
@ -203,9 +224,9 @@ class Shell:
# directory = self.getcwd() + "/" + directory # directory = self.getcwd() + "/" + directory
directory = self.path(directory) directory = self.path(directory)
if not self.exists(directory): if not self.exists(directory):
raise ValueError("Directory does not exist") raise ValueError(f"Directory '{directory}' does not exist")
if not self.isdir(directory): if not self.isdir(directory):
raise ValueError("Given location is not a directory") raise ValueError(f"The given location '{directory}' is not a directory")
os.chdir(directory) os.chdir(directory)
def pushd(self, directory): def pushd(self, directory):