[PATCH] Harden os.system
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
[PATCH] Harden os.system
From: Bryan O'Sullivan <bos@serpentine.com>
Add util.system function. This is similar to os.system, but will
either succeed (if the process finishes with a zero exit code) or raise
a util.CommandError (if the process exits uncleanly or is killed by
a signal).
Add util.explain_exit function. This tends to be ubiquitous in code
that calls other processes, and must describe what has gone wrong.
Change some uses of os.system over to util.system.
manifest hash:
e3bf4adcac5b915432ec0af00efdbcef86bea4b1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCwSipywK+sNU5EO8RAr0RAJkBDt8XQ7mYQAWNHNgTOVt1eyWU1QCfe1oO
2OwxyWqpbRNACVJHHfZ3/Xw=
=OaRX
-----END PGP SIGNATURE-----
--- a/mercurial/commands.py Tue Jun 28 02:34:14 2005 -0800
+++ b/mercurial/commands.py Tue Jun 28 02:38:33 2005 -0800
@@ -291,7 +291,7 @@
if link:
ui.debug("copying by hardlink\n")
- os.system("cp -al %s/.hg .hg" % source)
+ util.system("cp -al %s/.hg .hg" % source)
try:
os.remove(".hg/dirstate")
except: pass
@@ -871,6 +871,8 @@
return r
else:
return d()
+ except util.CommandError, inst:
+ u.warn("abort: %s\n" % inst.args)
except hg.RepoError, inst:
u.warn("abort: ", inst, "!\n")
except SignalInterrupt:
--- a/mercurial/ui.py Tue Jun 28 02:34:14 2005 -0800
+++ b/mercurial/ui.py Tue Jun 28 02:38:33 2005 -0800
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-import os, sys, re, ConfigParser
+import os, sys, re, ConfigParser, util
class ui:
def __init__(self, verbose=False, debug=False, quiet=False,
@@ -78,10 +78,7 @@
f.close()
editor = os.environ.get("HGEDITOR") or os.environ.get("EDITOR", "vi")
- r = os.system("%s %s" % (editor, name))
-
- if r:
- raise "Edit failed!"
+ util.system("%s %s" % (editor, name), errprefix = "edit failed")
t = open(name).read()
t = re.sub("(?m)^HG:.*\n", "", t)
--- a/mercurial/util.py Tue Jun 28 02:34:14 2005 -0800
+++ b/mercurial/util.py Tue Jun 28 02:38:33 2005 -0800
@@ -7,6 +7,29 @@
import os
+class CommandError(Exception): pass
+
+def explain_exit(code):
+ """return a 2-tuple (desc, code) describing a process's status"""
+ if os.WIFEXITED(code):
+ val = os.WEXITSTATUS(code)
+ return "exited with status %d" % val, val
+ elif os.WIFSIGNALED(code):
+ val = os.WTERMSIG(code)
+ return "killed by signal %d" % val, val
+ elif os.WIFSTOPPED(code):
+ val = os.STOPSIG(code)
+ return "stopped by signal %d" % val, val
+ raise ValueError("invalid exit code")
+
+def system(cmd, errprefix = "abort"):
+ """execute a shell command that must succeed"""
+ rc = os.system(cmd)
+ if rc:
+ errmsg = "%s: %s %s" % (errprefix, os.path.basename(cmd.split(None, 1)[0]),
+ explain_exit(rc)[0])
+ raise CommandError(errmsg)
+
def rename(src, dst):
try:
os.rename(src, dst)