+import sys, os, subprocess, tempfile, threading
+
+
+def which(program):
+ # https://stackoverflow.com/a/377028
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, _ = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
+
+def cmd(command):
+ # https://stackoverflow.com/a/4408409
+ # https://stackoverflow.com/a/10012262
+ with tempfile.TemporaryFile() as tempf:
+ p = subprocess.Popen (command, stderr=tempf)
+ is_killed = {'value': False}
+
+ def timeout(p, is_killed):
+ is_killed['value'] = True
+ p.kill()
+ timer = threading.Timer (2, timeout, [p, is_killed])
+
+ try:
+ timer.start()
+ p.wait ()
+ tempf.seek (0)
+ text = tempf.read().decode ("utf-8").strip ()
+ returncode = p.returncode
+ finally:
+ timer.cancel()
+
+ if is_killed['value']:
+ text = 'error: timeout, ' + text
+ returncode = 1
+
+ return text, returncode
+