Skip to content

Commit

Permalink
Merge 2378208 into a096704
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminGruner committed Aug 4, 2020
2 parents a096704 + 2378208 commit 35583fb
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 24 deletions.
13 changes: 8 additions & 5 deletions psutil/_psbsd.py
Expand Up @@ -51,7 +51,7 @@
cext.SWAIT: _common.STATUS_WAITING,
cext.SLOCK: _common.STATUS_LOCKED,
}
elif OPENBSD or NETBSD:
elif OPENBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SSLEEP: _common.STATUS_SLEEPING,
Expand All @@ -76,12 +76,11 @@
elif NETBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SACTIVE: _common.STATUS_RUNNING,
cext.SDYING: _common.STATUS_ZOMBIE,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SSTOP: _common.STATUS_STOPPED,
cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SDEAD: _common.STATUS_DEAD,
cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD
cext.SRUN: _common.STATUS_WAKING,
cext.SONPROC: _common.STATUS_RUNNING,
}

TCP_STATUSES = {
Expand Down Expand Up @@ -669,6 +668,10 @@ def cmdline(self):
else:
return cext.proc_cmdline(self.pid)

@wrap_exceptions
def environ(self):
return cext.proc_environ(self.pid)

@wrap_exceptions
def terminal(self):
tty_nr = self.oneshot()[kinfo_proc_map['ttynr']]
Expand Down
116 changes: 115 additions & 1 deletion psutil/_psutil_bsd.c
Expand Up @@ -57,6 +57,7 @@
#include <net/route.h>
#include <netinet/in.h> // process open files/connections
#include <sys/un.h>
#include <kvm.h>

#include "_psutil_common.h"
#include "_psutil_posix.h"
Expand All @@ -74,6 +75,10 @@
#else
#include <utmpx.h>
#endif
#include <fcntl.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#elif PSUTIL_OPENBSD
#include "arch/openbsd/specific.h"

Expand Down Expand Up @@ -391,6 +396,109 @@ psutil_proc_cmdline(PyObject *self, PyObject *args) {
}


/*
* Return process environment as a Python dictionary
*/
PyObject *
psutil_proc_environ(PyObject *self, PyObject *args) {
unsigned int i, cnt = 0;
long pid;
char *s, **envs, errbuf[_POSIX2_LINE_MAX];
PyObject *py_err=NULL, *py_value=NULL, *py_retdict=NULL;
kvm_t *kd;
#ifdef PSUTIL_NETBSD
struct kinfo_proc2 *p;
#else
struct kinfo_proc *p;
#endif

if (!PyArg_ParseTuple(args, "l", &pid))
return NULL;

#if defined(PSUTIL_FREEBSD)
kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
#else
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
#endif
if (!kd) {
convert_kvm_err("kvm_openfiles", errbuf);
return NULL;
}

py_retdict = PyDict_New();
if (!py_retdict)
goto error;

#if defined(PSUTIL_FREEBSD)
p = kvm_getprocs(kd, KERN_PROC_PID, pid, (int *)&cnt);
#elif defined(PSUTIL_OPENBSD)
p = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(*p), &cnt);
#elif defined(PSUTIL_NETBSD)
p = kvm_getproc2(kd, KERN_PROC_PID, pid, sizeof(*p), &cnt);
#endif
if (!p) {
py_err = NoSuchProcess("kvm_getprocs");
goto error;
}
if (!cnt) {
py_err = NoSuchProcess("kvm_getprocs: cnt==0");
goto error;
}

/* On *BSD kernels there are a few kernel-only system processes without an environment.
* To make unittest suite happy, return an empty environment
* (See e.g. "procstat -e 0 | 1 | 2 ..." on FreeBSD.)
*/
if (p->ki_ppid == 0) {
/* Process is a direct [kernel-only] descendant of process 0 */
kvm_close(kd);
return py_retdict;
}


#if defined(PSUTIL_NETBSD)
envs = kvm_getenvv2(kd, p, 0);
#else
envs = kvm_getenvv(kd, p, 0);
#endif
if (!envs) {
/* Map the most obvious stuff to general exceptions exported by "psutil" */
if (errno == EPERM)
py_err = AccessDenied("kvm_getenvv");
else if (errno == ESRCH)
py_err = NoSuchProcess("kvm_getenvv");
else
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}

/* Indicate we need to return libpython error if we return failure */
errno = 0;

for (i = 0; envs[i] != NULL; i++) {
s = strchr(envs[i], '=');
if (!s)
continue;
*s++ = 0;
py_value = PyUnicode_DecodeFSDefault(s);
if (!py_value)
goto error;
if (PyDict_SetItemString(py_retdict, envs[i], py_value)) {
goto error;
}
Py_DECREF(py_value);
}

kvm_close(kd);
return py_retdict;

error:
Py_XDECREF(py_value);
Py_XDECREF(py_retdict);
kvm_close(kd);
return py_err;
}

/*
* Return the number of logical CPUs in the system.
* XXX this could be shared with macOS
Expand Down Expand Up @@ -627,8 +735,10 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
strlcat(opts, ",noclusterr", sizeof(opts));
if (flags & MNT_NOCLUSTERW)
strlcat(opts, ",noclusterw", sizeof(opts));
#ifdef MNT_NFS4ACLS
if (flags & MNT_NFS4ACLS)
strlcat(opts, ",nfs4acls", sizeof(opts));
#endif
#elif PSUTIL_NETBSD
if (flags & MNT_NODEV)
strlcat(opts, ",nodev", sizeof(opts));
Expand Down Expand Up @@ -831,7 +941,7 @@ psutil_users(PyObject *self, PyObject *args) {
py_tty, // tty
py_hostname, // hostname
(float)ut.ut_time, // start time
#ifdef PSUTIL_OPENBSD
#if defined(PSUTIL_OPENBSD) || (defined(__FreeBSD_version) && __FreeBSD_version < 900000)
-1 // process id (set to None later)
#else
ut.ut_pid // TODO: use PyLong_FromPid
Expand Down Expand Up @@ -956,6 +1066,8 @@ static PyMethodDef mod_methods[] = {
{"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS,
"Return an XML string to determine the number physical CPUs."},
#endif
{"proc_environ", psutil_proc_environ, METH_VARARGS,
"Return process environment"},

// --- system-related functions

Expand Down Expand Up @@ -1060,7 +1172,9 @@ static PyMethodDef mod_methods[] = {
if (PyModule_AddIntConstant(mod, "SSLEEP", LSSLEEP)) INITERR;
if (PyModule_AddIntConstant(mod, "SSTOP", LSSTOP)) INITERR;
if (PyModule_AddIntConstant(mod, "SZOMB", LSZOMB)) INITERR;
#if __NetBSD_Version__ < 500000000
if (PyModule_AddIntConstant(mod, "SDEAD", LSDEAD)) INITERR;
#endif
if (PyModule_AddIntConstant(mod, "SONPROC", LSONPROC)) INITERR;
// unique to NetBSD
if (PyModule_AddIntConstant(mod, "SSUSPENDED", LSSUSPENDED)) INITERR;
Expand Down
20 changes: 20 additions & 0 deletions psutil/_psutil_common.c
Expand Up @@ -167,6 +167,26 @@ psutil_setup(void) {
}


// ============================================================================
// Utility functions (BSD)
// ============================================================================

#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
void
convert_kvm_err(const char *syscall, char *errbuf) {
char fullmsg[8192];

sprintf(fullmsg, "(originated from %s: %s)", syscall, errbuf);
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied(fullmsg);
else if (strstr(errbuf, "Operation not permitted") != NULL)
AccessDenied(fullmsg);
else
PyErr_Format(PyExc_RuntimeError, fullmsg);
}
#endif


// ====================================================================
// --- Windows
// ====================================================================
Expand Down
6 changes: 6 additions & 0 deletions psutil/_psutil_common.h
Expand Up @@ -104,6 +104,12 @@ PyObject* psutil_set_testing(PyObject *self, PyObject *args);
void psutil_debug(const char* format, ...);
int psutil_setup(void);

// ====================================================================
// --- BSD
// ====================================================================

void convert_kvm_err(const char *syscall, char *errbuf);

// ====================================================================
// --- Windows
// ====================================================================
Expand Down
4 changes: 3 additions & 1 deletion psutil/arch/freebsd/specific.c
Expand Up @@ -517,7 +517,7 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
}


#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
#if defined(__FreeBSD_version) && __FreeBSD_version >= 701000
PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args) {
pid_t pid;
Expand Down Expand Up @@ -795,9 +795,11 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args) {
case KVME_TYPE_DEAD:
path = "[dead]";
break;
#ifdef KVME_TYPE_SG
case KVME_TYPE_SG:
path = "[sg]";
break;
#endif
case KVME_TYPE_UNKNOWN:
path = "[unknown]";
break;
Expand Down
5 changes: 4 additions & 1 deletion psutil/arch/freebsd/sys_socks.c
Expand Up @@ -16,6 +16,9 @@
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/sysctl.h>
#if defined(__FreeBSD_version) && __FreeBSD_version < 800000
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h> // for xinpcb struct
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
Expand All @@ -30,7 +33,7 @@ static int psutil_nxfiles;


int
psutil_populate_xfiles() {
psutil_populate_xfiles(void) {
size_t len;

if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) {
Expand Down
14 changes: 0 additions & 14 deletions psutil/arch/openbsd/specific.c
Expand Up @@ -47,20 +47,6 @@
// ============================================================================


static void
convert_kvm_err(const char *syscall, char *errbuf) {
char fullmsg[8192];

sprintf(fullmsg, "(originated from %s: %s)", syscall, errbuf);
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied(fullmsg);
else if (strstr(errbuf, "Operation not permitted") != NULL)
AccessDenied(fullmsg);
else
PyErr_Format(PyExc_RuntimeError, fullmsg);
}


int
psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
// Fills a kinfo_proc struct based on process pid.
Expand Down
3 changes: 2 additions & 1 deletion psutil/tests/test_contracts.py
Expand Up @@ -137,7 +137,8 @@ class TestAvailProcessAPIs(PsutilTestCase):

def test_environ(self):
self.assertEqual(hasattr(psutil.Process, "environ"),
LINUX or MACOS or WINDOWS or AIX or SUNOS)
LINUX or MACOS or WINDOWS or AIX or SUNOS or
FREEBSD or OPENBSD or NETBSD)

def test_uids(self):
self.assertEqual(hasattr(psutil.Process, "uids"), POSIX)
Expand Down
2 changes: 1 addition & 1 deletion psutil/tests/test_process.py
Expand Up @@ -298,7 +298,7 @@ def test_create_time(self):
@unittest.skipIf(TRAVIS or CIRRUS, 'not reliable on TRAVIS/CIRRUS')
def test_terminal(self):
terminal = psutil.Process().terminal()
if sys.stdout.isatty():
if sys.stdin.isatty():
tty = os.path.realpath(sh('tty'))
self.assertEqual(terminal, tty)
else:
Expand Down

0 comments on commit 35583fb

Please sign in to comment.