Merge lp:~cjwatson/launchpad/shhh-no-shell into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18464
Proposed branch: lp:~cjwatson/launchpad/shhh-no-shell
Merge into: lp:launchpad
Diff against target: 106 lines (+31/-19)
1 file modified
utilities/shhh.py (+31/-19)
To merge this branch: bzr merge lp:~cjwatson/launchpad/shhh-no-shell
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+330155@code.launchpad.net

Commit message

Rework utilities/shhh.py to invoke the subsidiary command directly rather than via a shell.

Description of the change

shell=True delenda est.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)
Revision history for this message
Colin Watson (cjwatson) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'utilities/shhh.py'
2--- utilities/shhh.py 2012-01-01 03:10:25 +0000
3+++ utilities/shhh.py 2017-09-04 11:58:53 +0000
4@@ -1,14 +1,15 @@
5 #! /usr/bin/python -S
6 #
7-# Copyright 2009 Canonical Ltd. This software is licensed under the
8+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
9 # GNU Affero General Public License version 3 (see the file LICENSE).
10
11 """
12-Run a command and suppress output unless it returns a non-zero exit status
13+Run a command and suppress output unless it returns a non-zero exit status.
14 """
15
16 __metaclass__ = type
17
18+import os
19 from subprocess import (
20 PIPE,
21 Popen,
22@@ -23,49 +24,62 @@
23 order may be messed up if the command attempts to control order by
24 flushing stdout at points or setting it to unbuffered.
25
26-
27 To test, we invoke both this method and this script with some commands
28- and examine the output and exitvalue
29+ and examine the output and exit status.
30
31 >>> python = sys.executable
32
33 >>> def shhh_script(cmd):
34 ... from subprocess import Popen, PIPE
35- ... script = '%s %s' % (python, __file__)
36- ... cmd = "%s '%s'" % (script, cmd)
37- ... p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
38+ ... cmd = [python, __file__] + cmd
39+ ... p = Popen(cmd, stdout=PIPE, stderr=PIPE)
40 ... (out, err) = p.communicate()
41 ... return (out, err, p.returncode)
42
43- >>> cmd = '''%s -c "import sys; sys.exit(%d)"''' % (python, 0)
44+ >>> cmd = [python, "-c", "import sys; sys.exit(0)"]
45 >>> shhh(cmd)
46 0
47 >>> shhh_script(cmd)
48 ('', '', 0)
49
50- >>> cmd = '''%s -c "import sys; sys.exit(%d)"''' % (python, 1)
51+ >>> cmd = [python, "-c", "import sys; sys.exit(1)"]
52 >>> shhh(cmd)
53 1
54 >>> shhh_script(cmd)
55 ('', '', 1)
56
57- >>> cmd = '''%s -c "import sys; print 666; sys.exit(%d)"''' % (
58- ... python, 42)
59+ >>> cmd = [python, "-c", "import sys; print 666; sys.exit(42)"]
60 >>> shhh(cmd)
61 666
62 42
63 >>> shhh_script(cmd)
64 ('666\n', '', 42)
65
66- >>> cmd = (
67- ... '''%s -c "import sys; print 666; '''
68- ... '''print >> sys.stderr, 667; sys.exit(42)"''' % python
69- ... )
70+ >>> cmd = [
71+ ... python, "-c",
72+ ... "import sys; print 666; print >> sys.stderr, 667; sys.exit(42)",
73+ ... ]
74 >>> shhh_script(cmd)
75 ('666\n', '667\n', 42)
76+
77+ >>> cmd = ["TEST=sentinel value=0", "sh", "-c", 'echo "$TEST"; exit 1']
78+ >>> shhh(cmd)
79+ sentinel value=0
80+ 1
81+ >>> shhh_script(cmd)
82+ ('sentinel value=0\n', '', 1)
83 """
84
85- process = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
86+ env = dict(os.environ)
87+ cmd = list(cmd)
88+ while cmd:
89+ if "=" in cmd[0]:
90+ name, value = cmd[0].split("=", 1)
91+ env[name] = value
92+ del cmd[0]
93+ else:
94+ break
95+ process = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
96 (out, err) = process.communicate()
97 if process.returncode == 0:
98 return 0
99@@ -76,6 +90,4 @@
100
101
102 if __name__ == '__main__':
103- cmd = ' '.join(sys.argv[1:])
104- sys.exit(shhh(cmd))
105-
106+ sys.exit(shhh(sys.argv[1:]))