/usr/share/pyshared/nemu/environ.py is in python-nemu 0.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | # vim:ts=4:sw=4:et:ai:sts=4
# -*- coding: utf-8 -*-
# Copyright 2010, 2011 INRIA
# Copyright 2011 MartÃn Ferrari <martin.ferrari@gmail.com>
#
# This file is part of Nemu.
#
# Nemu is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License version 2, as published by the Free
# Software Foundation.
#
# Nemu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# Nemu. If not, see <http://www.gnu.org/licenses/>.
import errno, os, os.path, socket, subprocess, sys, syslog
from syslog import LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
__all__ = ["IP_PATH", "TC_PATH", "BRCTL_PATH", "SYSCTL_PATH", "HZ"]
__all__ += ["TCPDUMP_PATH", "NETPERF_PATH", "XAUTH_PATH", "XDPYINFO_PATH"]
__all__ += ["execute", "backticks", "eintr_wrapper"]
__all__ += ["find_listen_port"]
__all__ += ["LOG_ERR", "LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG"]
__all__ += ["set_log_level", "logger"]
__all__ += ["error", "warning", "notice", "info", "debug"]
def find_bin(name, extra_path = None):
"""Try hard to find the location of needed programs."""
search = []
if "PATH" in os.environ:
search += os.environ["PATH"].split(":")
search.extend(os.path.join(x, y)
for x in ("/", "/usr/", "/usr/local/")
for y in ("bin", "sbin"))
if extra_path:
search += extra_path
for dirr in search:
path = os.path.join(dirr, name)
if os.path.exists(path):
return path
return None
def find_bin_or_die(name, extra_path = None):
"""Try hard to find the location of needed programs; raise on failure."""
res = find_bin(name, extra_path)
if not res:
raise RuntimeError("Cannot find `%s', impossible to continue." % name)
return res
IP_PATH = find_bin_or_die("ip")
TC_PATH = find_bin_or_die("tc")
BRCTL_PATH = find_bin_or_die("brctl")
SYSCTL_PATH = find_bin_or_die("sysctl")
# Optional tools
TCPDUMP_PATH = find_bin("tcpdump")
NETPERF_PATH = find_bin("netperf")
XAUTH_PATH = find_bin("xauth")
XDPYINFO_PATH = find_bin("xdpyinfo")
# Seems this is completely bogus. At least, we can assume that the internal HZ
# is bigger than this.
HZ = os.sysconf("SC_CLK_TCK")
try:
os.stat("/sys/class/net")
except:
raise RuntimeError("Sysfs does not seem to be mounted, impossible to " +
"continue.")
def execute(cmd):
"""Execute a command, if the return value is non-zero, raise an exception.
Raises:
RuntimeError: the command was unsuccessful (return code != 0).
"""
debug("execute(%s)" % cmd)
null = open("/dev/null", "r+")
proc = subprocess.Popen(cmd, stdout = null, stderr = subprocess.PIPE)
_, err = proc.communicate()
if proc.returncode != 0:
raise RuntimeError("Error executing `%s': %s" % (" ".join(cmd), err))
def backticks(cmd):
"""Execute a command and capture its output.
If the return value is non-zero, raise an exception.
Returns:
(stdout, stderr): tuple containing the captured output.
Raises:
RuntimeError: the command was unsuccessful (return code != 0).
"""
debug("backticks(%s)" % cmd)
proc = subprocess.Popen(cmd, stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
out, err = proc.communicate()
if proc.returncode != 0:
raise RuntimeError("Error executing `%s': %s" % (" ".join(cmd), err))
return out
def eintr_wrapper(func, *args):
"Wraps some callable with a loop that retries on EINTR."
while True:
try:
return func(*args)
except OSError, ex: # pragma: no cover
if ex.errno == errno.EINTR:
continue
raise
except IOError, ex: # pragma: no cover
if ex.errno == errno.EINTR:
continue
raise
def find_listen_port(family = socket.AF_INET, type = socket.SOCK_STREAM,
proto = 0, addr = "127.0.0.1", min_port = 1, max_port = 65535):
sock = socket.socket(family, type, proto)
for port in range(min_port, max_port + 1):
try:
sock.bind((addr, port))
return sock, port
except socket.error:
pass
raise RuntimeError("Cannot find an usable port in the range specified")
# Logging
_log_level = LOG_WARNING
_log_use_syslog = False
_log_stream = sys.stderr
_log_syslog_opts = ()
_log_pid = os.getpid()
def set_log_level(level):
"Sets the log level for console messages, does not affect syslog logging."
global _log_level
assert level > LOG_ERR and level <= LOG_DEBUG
_log_level = level
def set_log_output(stream):
"Redirect console messages to the provided stream."
global _log_stream
assert hasattr(stream, "write") and hasattr(stream, "flush")
_log_stream = stream
def log_use_syslog(use = True, ident = None, logopt = 0,
facility = syslog.LOG_USER):
"Enable or disable the use of syslog for logging messages."
global _log_use_syslog, _log_syslog_opts
_log_syslog_opts = (ident, logopt, facility)
_log_use_syslog = use
_init_log()
def _init_log():
if not _log_use_syslog:
syslog.closelog()
return
(ident, logopt, facility) = _log_syslog_opts
if not ident:
#ident = os.path.basename(sys.argv[0])
ident = "nemu"
syslog.openlog("%s[%d]" % (ident, os.getpid()), logopt, facility)
info("Syslog logging started")
def logger(priority, message):
"Print a log message in syslog, console or both."
if _log_use_syslog:
if os.getpid() != _log_pid:
_init_log() # Need to tell syslog the new PID.
syslog.syslog(priority, message)
return
if priority > _log_level:
return
eintr_wrapper(_log_stream.write,
"[%d] %s\n" % (os.getpid(), message.rstrip()))
_log_stream.flush()
def error(message):
logger(LOG_ERR, message)
def warning(message):
logger(LOG_WARNING, message)
def notice(message):
logger(LOG_NOTICE, message)
def info(message):
logger(LOG_INFO, message)
def debug(message):
logger(LOG_DEBUG, message)
def _custom_hook(tipe, value, traceback): # pragma: no cover
"""Custom exception hook, to print nested exceptions information."""
if hasattr(value, "child_traceback"):
sys.stderr.write("Nested exception, original traceback " +
"(most recent call last):\n")
sys.stderr.write(value.child_traceback + ("-" * 70) + "\n")
sys.__excepthook__(tipe, value, traceback)
sys.excepthook = _custom_hook
|