summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2023-04-20 20:19:12 +0200
committerGitHub <noreply@github.com>2023-04-20 20:19:12 +0200
commit747965f6dbffe0a664a2ae7816f6d9b9a0f83fb5 (patch)
treeca633b0a99273889e2a7aeabbfae84df9f461347
parent6e23a5129375ae19abadc0de49f920899b6e765c (diff)
downloadpsutil-747965f6dbffe0a664a2ae7816f6d9b9a0f83fb5.tar.gz
OSX / refact: get rid of process_info.c (#2243)
-rw-r--r--MANIFEST.in2
-rw-r--r--docs/index.rst2
-rw-r--r--psutil/_psutil_osx.c1
-rw-r--r--psutil/arch/osx/proc.c399
-rw-r--r--psutil/arch/osx/proc.h2
-rw-r--r--psutil/arch/osx/process_info.c408
-rw-r--r--psutil/arch/osx/process_info.h18
-rwxr-xr-xsetup.py1
8 files changed, 397 insertions, 436 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 82d0e9a7..8defe717 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -101,8 +101,6 @@ include psutil/arch/osx/net.c
include psutil/arch/osx/net.h
include psutil/arch/osx/proc.c
include psutil/arch/osx/proc.h
-include psutil/arch/osx/process_info.c
-include psutil/arch/osx/process_info.h
include psutil/arch/osx/sensors.c
include psutil/arch/osx/sensors.h
include psutil/arch/osx/sys.c
diff --git a/docs/index.rst b/docs/index.rst
index 344aecdf..2bf050a1 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -2602,7 +2602,7 @@ On Windows:
::
set PSUTIL_DEBUG=1 python.exe script.py
- psutil-debug [psutil/arch/windows/process_info.c:90]> NtWow64ReadVirtualMemory64(pbi64.PebBaseAddress) -> 998 (Unknown error) (ignored)
+ psutil-debug [psutil/arch/windows/proc.c:90]> NtWow64ReadVirtualMemory64(pbi64.PebBaseAddress) -> 998 (Unknown error) (ignored)
Security
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
index 59fe5b68..dd7168eb 100644
--- a/psutil/_psutil_osx.c
+++ b/psutil/_psutil_osx.c
@@ -16,7 +16,6 @@
#include "arch/osx/mem.h"
#include "arch/osx/net.h"
#include "arch/osx/proc.h"
-#include "arch/osx/process_info.h"
#include "arch/osx/sensors.h"
#include "arch/osx/sys.h"
diff --git a/psutil/arch/osx/proc.c b/psutil/arch/osx/proc.c
index 948d080b..6f66c861 100644
--- a/psutil/arch/osx/proc.c
+++ b/psutil/arch/osx/proc.c
@@ -5,9 +5,10 @@
*/
// Process related functions. Original code was moved in here from
-// psutil/_psutil_osx.c in 2023. For reference, here's the GIT blame
-// history before the move:
+// psutil/_psutil_osx.c and psutil/arc/osx/process_info.c in 2023.
+// For reference, here's the GIT blame history before the move:
// https://github.com/giampaolo/psutil/blame/59504a5/psutil/_psutil_osx.c
+// https://github.com/giampaolo/psutil/blame/efd7ed3/psutil/arch/osx/process_info.c
#include <Python.h>
#include <assert.h>
@@ -30,10 +31,196 @@
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
-#include "process_info.h"
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
+typedef struct kinfo_proc kinfo_proc;
+
+
+// ====================================================================
+// --- utils
+// ====================================================================
+
+/*
+ * Returns a list of all BSD processes on the system. This routine
+ * allocates the list and puts it in *procList and a count of the
+ * number of entries in *procCount. You are responsible for freeing
+ * this list (use "free" from System framework).
+ * On success, the function returns 0.
+ * On error, the function returns a BSD errno value.
+ */
+static int
+psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
+ int mib[3];
+ size_t size, size2;
+ void *ptr;
+ int err;
+ int lim = 8; // some limit
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+ *procCount = 0;
+
+ /*
+ * We start by calling sysctl with ptr == NULL and size == 0.
+ * That will succeed, and set size to the appropriate length.
+ * We then allocate a buffer of at least that size and call
+ * sysctl with that buffer. If that succeeds, we're done.
+ * If that call fails with ENOMEM, we throw the buffer away
+ * and try again.
+ * Note that the loop calls sysctl with NULL again. This is
+ * is necessary because the ENOMEM failure case sets size to
+ * the amount of data returned, not the amount of data that
+ * could have been returned.
+ */
+ while (lim-- > 0) {
+ size = 0;
+ if (sysctl((int *)mib, 3, NULL, &size, NULL, 0) == -1) {
+ PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)");
+ return 1;
+ }
+ size2 = size + (size >> 3); // add some
+ if (size2 > size) {
+ ptr = malloc(size2);
+ if (ptr == NULL)
+ ptr = malloc(size);
+ else
+ size = size2;
+ }
+ else {
+ ptr = malloc(size);
+ }
+ if (ptr == NULL) {
+ PyErr_NoMemory();
+ return 1;
+ }
+
+ if (sysctl((int *)mib, 3, ptr, &size, NULL, 0) == -1) {
+ err = errno;
+ free(ptr);
+ if (err != ENOMEM) {
+ PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)");
+ return 1;
+ }
+ }
+ else {
+ *procList = (kinfo_proc *)ptr;
+ *procCount = size / sizeof(kinfo_proc);
+ if (procCount <= 0) {
+ PyErr_Format(PyExc_RuntimeError, "no PIDs found");
+ return 1;
+ }
+ return 0; // success
+ }
+ }
+
+ PyErr_Format(PyExc_RuntimeError, "couldn't collect PIDs list");
+ return 1;
+}
+
+
+// Read the maximum argument size for processes
+static int
+psutil_sysctl_argmax() {
+ int argmax;
+ int mib[2];
+ size_t size = sizeof(argmax);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+
+ if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0)
+ return argmax;
+ PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_ARGMAX)");
+ return 0;
+}
+
+
+// Read process argument space.
+static int
+psutil_sysctl_procargs(pid_t pid, char *procargs, size_t *argmax) {
+ int mib[3];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCARGS2;
+ mib[2] = pid;
+
+ if (sysctl(mib, 3, procargs, argmax, NULL, 0) < 0) {
+ if (psutil_pid_exists(pid) == 0) {
+ NoSuchProcess("psutil_pid_exists -> 0");
+ return 1;
+ }
+ // In case of zombie process we'll get EINVAL. We translate it
+ // to NSP and _psosx.py will translate it to ZP.
+ if (errno == EINVAL) {
+ psutil_debug("sysctl(KERN_PROCARGS2) -> EINVAL translated to NSP");
+ NoSuchProcess("sysctl(KERN_PROCARGS2) -> EINVAL");
+ return 1;
+ }
+ // There's nothing we can do other than raising AD.
+ if (errno == EIO) {
+ psutil_debug("sysctl(KERN_PROCARGS2) -> EIO translated to AD");
+ AccessDenied("sysctl(KERN_PROCARGS2) -> EIO");
+ return 1;
+ }
+ PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROCARGS2)");
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) {
+ int mib[4];
+ size_t len;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+
+ // fetch the info with sysctl()
+ len = sizeof(struct kinfo_proc);
+
+ // now read the data from sysctl
+ if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) {
+ // raise an exception and throw errno as the error
+ PyErr_SetFromOSErrnoWithSyscall("sysctl");
+ return -1;
+ }
+
+ // sysctl succeeds but len is zero, happens when process has gone away
+ if (len == 0) {
+ NoSuchProcess("sysctl(kinfo_proc), len == 0");
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * A wrapper around proc_pidinfo().
+ * https://opensource.apple.com/source/xnu/xnu-2050.7.9/bsd/kern/proc_info.c
+ * Returns 0 on failure.
+ */
+static int
+psutil_proc_pidinfo(pid_t pid, int flavor, uint64_t arg, void *pti, int size) {
+ errno = 0;
+ int ret;
+
+ ret = proc_pidinfo(pid, flavor, arg, pti, size);
+ if (ret <= 0) {
+ psutil_raise_for_pid(pid, "proc_pidinfo()");
+ return 0;
+ }
+ if ((unsigned long)ret < sizeof(pti)) {
+ psutil_raise_for_pid(
+ pid, "proc_pidinfo() return size < sizeof(struct_pointer)");
+ return 0;
+ }
+ return ret;
+}
/*
@@ -50,7 +237,7 @@
* https://github.com/giampaolo/psutil/issues/1209
* https://github.com/giampaolo/psutil/issues/1291#issuecomment-396062519
*/
-int
+static int
psutil_task_for_pid(pid_t pid, mach_port_t *task)
{
// See: https://github.com/giampaolo/psutil/issues/1181
@@ -68,7 +255,7 @@ psutil_task_for_pid(pid_t pid, mach_port_t *task)
psutil_debug(
"task_for_pid() failed (pid=%ld, err=%i, errno=%i, msg='%s'); "
"setting AccessDenied()",
- pid, err, errno, mach_error_string(err));
+ (long)pid, err, errno, mach_error_string(err));
AccessDenied("task_for_pid");
}
return 1;
@@ -143,6 +330,11 @@ error:
}
+// ====================================================================
+// --- Python APIs
+// ====================================================================
+
+
/*
* Return a Python list of all the PIDs running on the system.
*/
@@ -876,3 +1068,200 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) {
free(fds_pointer);
return Py_BuildValue("i", num_fds);
}
+
+
+// return process args as a python list
+PyObject *
+psutil_proc_cmdline(PyObject *self, PyObject *args) {
+ pid_t pid;
+ int nargs;
+ size_t len;
+ char *procargs = NULL;
+ char *arg_ptr;
+ char *arg_end;
+ char *curr_arg;
+ size_t argmax;
+ PyObject *py_retlist = PyList_New(0);
+ PyObject *py_arg = NULL;
+
+ if (py_retlist == NULL)
+ return NULL;
+ if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
+ goto error;
+
+ // special case for PID 0 (kernel_task) where cmdline cannot be fetched
+ if (pid == 0)
+ return py_retlist;
+
+ // read argmax and allocate memory for argument space.
+ argmax = psutil_sysctl_argmax();
+ if (! argmax)
+ goto error;
+
+ procargs = (char *)malloc(argmax);
+ if (NULL == procargs) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
+ if (psutil_sysctl_procargs(pid, procargs, &argmax) != 0)
+ goto error;
+
+ arg_end = &procargs[argmax];
+ // copy the number of arguments to nargs
+ memcpy(&nargs, procargs, sizeof(nargs));
+
+ arg_ptr = procargs + sizeof(nargs);
+ len = strlen(arg_ptr);
+ arg_ptr += len + 1;
+
+ if (arg_ptr == arg_end) {
+ free(procargs);
+ return py_retlist;
+ }
+
+ // skip ahead to the first argument
+ for (; arg_ptr < arg_end; arg_ptr++) {
+ if (*arg_ptr != '\0')
+ break;
+ }
+
+ // iterate through arguments
+ curr_arg = arg_ptr;
+ while (arg_ptr < arg_end && nargs > 0) {
+ if (*arg_ptr++ == '\0') {
+ py_arg = PyUnicode_DecodeFSDefault(curr_arg);
+ if (! py_arg)
+ goto error;
+ if (PyList_Append(py_retlist, py_arg))
+ goto error;
+ Py_DECREF(py_arg);
+ // iterate to next arg and decrement # of args
+ curr_arg = arg_ptr;
+ nargs--;
+ }
+ }
+
+ free(procargs);
+ return py_retlist;
+
+error:
+ Py_XDECREF(py_arg);
+ Py_XDECREF(py_retlist);
+ if (procargs != NULL)
+ free(procargs);
+ return NULL;
+}
+
+
+// Return process environment as a python string.
+// On Big Sur this function returns an empty string unless:
+// * kernel is DEVELOPMENT || DEBUG
+// * target process is same as current_proc()
+// * target process is not cs_restricted
+// * SIP is off
+// * caller has an entitlement
+// See: https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/kern/kern_sysctl.c#L1315-L1321
+PyObject *
+psutil_proc_environ(PyObject *self, PyObject *args) {
+ pid_t pid;
+ int nargs;
+ char *procargs = NULL;
+ char *procenv = NULL;
+ char *arg_ptr;
+ char *arg_end;
+ char *env_start;
+ size_t argmax;
+ PyObject *py_ret = NULL;
+
+ if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
+ return NULL;
+
+ // special case for PID 0 (kernel_task) where cmdline cannot be fetched
+ if (pid == 0)
+ goto empty;
+
+ // read argmax and allocate memory for argument space.
+ argmax = psutil_sysctl_argmax();
+ if (! argmax)
+ goto error;
+
+ procargs = (char *)malloc(argmax);
+ if (NULL == procargs) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
+ if (psutil_sysctl_procargs(pid, procargs, &argmax) != 0)
+ goto error;
+
+ arg_end = &procargs[argmax];
+ // copy the number of arguments to nargs
+ memcpy(&nargs, procargs, sizeof(nargs));
+
+ // skip executable path
+ arg_ptr = procargs + sizeof(nargs);
+ arg_ptr = memchr(arg_ptr, '\0', arg_end - arg_ptr);
+
+ if (arg_ptr == NULL || arg_ptr == arg_end) {
+ psutil_debug(
+ "(arg_ptr == NULL || arg_ptr == arg_end); set environ to empty");
+ goto empty;
+ }
+
+ // skip ahead to the first argument
+ for (; arg_ptr < arg_end; arg_ptr++) {
+ if (*arg_ptr != '\0')
+ break;
+ }
+
+ // iterate through arguments
+ while (arg_ptr < arg_end && nargs > 0) {
+ if (*arg_ptr++ == '\0')
+ nargs--;
+ }
+
+ // build an environment variable block
+ env_start = arg_ptr;
+
+ procenv = calloc(1, arg_end - arg_ptr);
+ if (procenv == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
+ while (*arg_ptr != '\0' && arg_ptr < arg_end) {
+ char *s = memchr(arg_ptr + 1, '\0', arg_end - arg_ptr);
+ if (s == NULL)
+ break;
+ memcpy(procenv + (arg_ptr - env_start), arg_ptr, s - arg_ptr);
+ arg_ptr = s + 1;
+ }
+
+ py_ret = PyUnicode_DecodeFSDefaultAndSize(
+ procenv, arg_ptr - env_start + 1);
+ if (!py_ret) {
+ // XXX: don't want to free() this as per:
+ // https://github.com/giampaolo/psutil/issues/926
+ // It sucks but not sure what else to do.
+ procargs = NULL;
+ goto error;
+ }
+
+ free(procargs);
+ free(procenv);
+ return py_ret;
+
+empty:
+ if (procargs != NULL)
+ free(procargs);
+ return Py_BuildValue("s", "");
+
+error:
+ Py_XDECREF(py_ret);
+ if (procargs != NULL)
+ free(procargs);
+ if (procenv != NULL)
+ free(procargs);
+ return NULL;
+}
diff --git a/psutil/arch/osx/proc.h b/psutil/arch/osx/proc.h
index 621f0cad..63f16ccd 100644
--- a/psutil/arch/osx/proc.h
+++ b/psutil/arch/osx/proc.h
@@ -7,8 +7,10 @@
#include <Python.h>
PyObject *psutil_pids(PyObject *self, PyObject *args);
+PyObject *psutil_proc_cmdline(PyObject *self, PyObject *args);
PyObject *psutil_proc_connections(PyObject *self, PyObject *args);
PyObject *psutil_proc_cwd(PyObject *self, PyObject *args);
+PyObject *psutil_proc_environ(PyObject *self, PyObject *args);
PyObject *psutil_proc_exe(PyObject *self, PyObject *args);
PyObject *psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args);
PyObject *psutil_proc_memory_uss(PyObject *self, PyObject *args);
diff --git a/psutil/arch/osx/process_info.c b/psutil/arch/osx/process_info.c
deleted file mode 100644
index 4b98d92a..00000000
--- a/psutil/arch/osx/process_info.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Helper functions related to fetching process information.
- * Used by _psutil_osx module methods.
- */
-
-
-#include <Python.h>
-#include <errno.h>
-#include <sys/sysctl.h>
-#include <libproc.h>
-
-#include "../../_psutil_common.h"
-#include "../../_psutil_posix.h"
-#include "process_info.h"
-
-
-/*
- * Returns a list of all BSD processes on the system. This routine
- * allocates the list and puts it in *procList and a count of the
- * number of entries in *procCount. You are responsible for freeing
- * this list (use "free" from System framework).
- * On success, the function returns 0.
- * On error, the function returns a BSD errno value.
- */
-int
-psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
- int mib[3];
- size_t size, size2;
- void *ptr;
- int err;
- int lim = 8; // some limit
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_ALL;
- *procCount = 0;
-
- /*
- * We start by calling sysctl with ptr == NULL and size == 0.
- * That will succeed, and set size to the appropriate length.
- * We then allocate a buffer of at least that size and call
- * sysctl with that buffer. If that succeeds, we're done.
- * If that call fails with ENOMEM, we throw the buffer away
- * and try again.
- * Note that the loop calls sysctl with NULL again. This is
- * is necessary because the ENOMEM failure case sets size to
- * the amount of data returned, not the amount of data that
- * could have been returned.
- */
- while (lim-- > 0) {
- size = 0;
- if (sysctl((int *)mib, 3, NULL, &size, NULL, 0) == -1) {
- PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)");
- return 1;
- }
- size2 = size + (size >> 3); // add some
- if (size2 > size) {
- ptr = malloc(size2);
- if (ptr == NULL)
- ptr = malloc(size);
- else
- size = size2;
- }
- else {
- ptr = malloc(size);
- }
- if (ptr == NULL) {
- PyErr_NoMemory();
- return 1;
- }
-
- if (sysctl((int *)mib, 3, ptr, &size, NULL, 0) == -1) {
- err = errno;
- free(ptr);
- if (err != ENOMEM) {
- PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)");
- return 1;
- }
- }
- else {
- *procList = (kinfo_proc *)ptr;
- *procCount = size / sizeof(kinfo_proc);
- if (procCount <= 0) {
- PyErr_Format(PyExc_RuntimeError, "no PIDs found");
- return 1;
- }
- return 0; // success
- }
- }
-
- PyErr_Format(PyExc_RuntimeError, "couldn't collect PIDs list");
- return 1;
-}
-
-
-// Read the maximum argument size for processes
-static int
-psutil_sysctl_argmax() {
- int argmax;
- int mib[2];
- size_t size = sizeof(argmax);
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_ARGMAX;
-
- if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0)
- return argmax;
- PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_ARGMAX)");
- return 0;
-}
-
-
-// Read process argument space.
-static int
-psutil_sysctl_procargs(pid_t pid, char *procargs, size_t *argmax) {
- int mib[3];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROCARGS2;
- mib[2] = pid;
-
- if (sysctl(mib, 3, procargs, argmax, NULL, 0) < 0) {
- if (psutil_pid_exists(pid) == 0) {
- NoSuchProcess("psutil_pid_exists -> 0");
- return 1;
- }
- // In case of zombie process we'll get EINVAL. We translate it
- // to NSP and _psosx.py will translate it to ZP.
- if (errno == EINVAL) {
- psutil_debug("sysctl(KERN_PROCARGS2) -> EINVAL translated to NSP");
- NoSuchProcess("sysctl(KERN_PROCARGS2) -> EINVAL");
- return 1;
- }
- // There's nothing we can do other than raising AD.
- if (errno == EIO) {
- psutil_debug("sysctl(KERN_PROCARGS2) -> EIO translated to AD");
- AccessDenied("sysctl(KERN_PROCARGS2) -> EIO");
- return 1;
- }
- PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROCARGS2)");
- return 1;
- }
- return 0;
-}
-
-
-// Return 1 if pid refers to a zombie process else 0.
-int
-psutil_is_zombie(pid_t pid) {
- struct kinfo_proc kp;
-
- if (psutil_get_kinfo_proc(pid, &kp) == -1)
- return 0;
- return (kp.kp_proc.p_stat == SZOMB) ? 1 : 0;
-}
-
-
-// return process args as a python list
-PyObject *
-psutil_proc_cmdline(PyObject *self, PyObject *args) {
- pid_t pid;
- int nargs;
- size_t len;
- char *procargs = NULL;
- char *arg_ptr;
- char *arg_end;
- char *curr_arg;
- size_t argmax;
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_arg = NULL;
-
- if (py_retlist == NULL)
- return NULL;
- if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
- goto error;
-
- // special case for PID 0 (kernel_task) where cmdline cannot be fetched
- if (pid == 0)
- return py_retlist;
-
- // read argmax and allocate memory for argument space.
- argmax = psutil_sysctl_argmax();
- if (! argmax)
- goto error;
-
- procargs = (char *)malloc(argmax);
- if (NULL == procargs) {
- PyErr_NoMemory();
- goto error;
- }
-
- if (psutil_sysctl_procargs(pid, procargs, &argmax) != 0)
- goto error;
-
- arg_end = &procargs[argmax];
- // copy the number of arguments to nargs
- memcpy(&nargs, procargs, sizeof(nargs));
-
- arg_ptr = procargs + sizeof(nargs);
- len = strlen(arg_ptr);
- arg_ptr += len + 1;
-
- if (arg_ptr == arg_end) {
- free(procargs);
- return py_retlist;
- }
-
- // skip ahead to the first argument
- for (; arg_ptr < arg_end; arg_ptr++) {
- if (*arg_ptr != '\0')
- break;
- }
-
- // iterate through arguments
- curr_arg = arg_ptr;
- while (arg_ptr < arg_end && nargs > 0) {
- if (*arg_ptr++ == '\0') {
- py_arg = PyUnicode_DecodeFSDefault(curr_arg);
- if (! py_arg)
- goto error;
- if (PyList_Append(py_retlist, py_arg))
- goto error;
- Py_DECREF(py_arg);
- // iterate to next arg and decrement # of args
- curr_arg = arg_ptr;
- nargs--;
- }
- }
-
- free(procargs);
- return py_retlist;
-
-error:
- Py_XDECREF(py_arg);
- Py_XDECREF(py_retlist);
- if (procargs != NULL)
- free(procargs);
- return NULL;
-}
-
-
-// Return process environment as a python string.
-// On Big Sur this function returns an empty string unless:
-// * kernel is DEVELOPMENT || DEBUG
-// * target process is same as current_proc()
-// * target process is not cs_restricted
-// * SIP is off
-// * caller has an entitlement
-// See: https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/kern/kern_sysctl.c#L1315-L1321
-PyObject *
-psutil_proc_environ(PyObject *self, PyObject *args) {
- pid_t pid;
- int nargs;
- char *procargs = NULL;
- char *procenv = NULL;
- char *arg_ptr;
- char *arg_end;
- char *env_start;
- size_t argmax;
- PyObject *py_ret = NULL;
-
- if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
- return NULL;
-
- // special case for PID 0 (kernel_task) where cmdline cannot be fetched
- if (pid == 0)
- goto empty;
-
- // read argmax and allocate memory for argument space.
- argmax = psutil_sysctl_argmax();
- if (! argmax)
- goto error;
-
- procargs = (char *)malloc(argmax);
- if (NULL == procargs) {
- PyErr_NoMemory();
- goto error;
- }
-
- if (psutil_sysctl_procargs(pid, procargs, &argmax) != 0)
- goto error;
-
- arg_end = &procargs[argmax];
- // copy the number of arguments to nargs
- memcpy(&nargs, procargs, sizeof(nargs));
-
- // skip executable path
- arg_ptr = procargs + sizeof(nargs);
- arg_ptr = memchr(arg_ptr, '\0', arg_end - arg_ptr);
-
- if (arg_ptr == NULL || arg_ptr == arg_end) {
- psutil_debug(
- "(arg_ptr == NULL || arg_ptr == arg_end); set environ to empty");
- goto empty;
- }
-
- // skip ahead to the first argument
- for (; arg_ptr < arg_end; arg_ptr++) {
- if (*arg_ptr != '\0')
- break;
- }
-
- // iterate through arguments
- while (arg_ptr < arg_end && nargs > 0) {
- if (*arg_ptr++ == '\0')
- nargs--;
- }
-
- // build an environment variable block
- env_start = arg_ptr;
-
- procenv = calloc(1, arg_end - arg_ptr);
- if (procenv == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- while (*arg_ptr != '\0' && arg_ptr < arg_end) {
- char *s = memchr(arg_ptr + 1, '\0', arg_end - arg_ptr);
- if (s == NULL)
- break;
- memcpy(procenv + (arg_ptr - env_start), arg_ptr, s - arg_ptr);
- arg_ptr = s + 1;
- }
-
- py_ret = PyUnicode_DecodeFSDefaultAndSize(
- procenv, arg_ptr - env_start + 1);
- if (!py_ret) {
- // XXX: don't want to free() this as per:
- // https://github.com/giampaolo/psutil/issues/926
- // It sucks but not sure what else to do.
- procargs = NULL;
- goto error;
- }
-
- free(procargs);
- free(procenv);
- return py_ret;
-
-empty:
- if (procargs != NULL)
- free(procargs);
- return Py_BuildValue("s", "");
-
-error:
- Py_XDECREF(py_ret);
- if (procargs != NULL)
- free(procargs);
- if (procenv != NULL)
- free(procargs);
- return NULL;
-}
-
-
-int
-psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) {
- int mib[4];
- size_t len;
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = pid;
-
- // fetch the info with sysctl()
- len = sizeof(struct kinfo_proc);
-
- // now read the data from sysctl
- if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) {
- // raise an exception and throw errno as the error
- PyErr_SetFromOSErrnoWithSyscall("sysctl");
- return -1;
- }
-
- // sysctl succeeds but len is zero, happens when process has gone away
- if (len == 0) {
- NoSuchProcess("sysctl(kinfo_proc), len == 0");
- return -1;
- }
- return 0;
-}
-
-
-/*
- * A wrapper around proc_pidinfo().
- * https://opensource.apple.com/source/xnu/xnu-2050.7.9/bsd/kern/proc_info.c
- * Returns 0 on failure.
- */
-int
-psutil_proc_pidinfo(pid_t pid, int flavor, uint64_t arg, void *pti, int size) {
- errno = 0;
- int ret;
-
- ret = proc_pidinfo(pid, flavor, arg, pti, size);
- if (ret <= 0) {
- psutil_raise_for_pid(pid, "proc_pidinfo()");
- return 0;
- }
- if ((unsigned long)ret < sizeof(pti)) {
- psutil_raise_for_pid(
- pid, "proc_pidinfo() return size < sizeof(struct_pointer)");
- return 0;
- }
- return ret;
-}
diff --git a/psutil/arch/osx/process_info.h b/psutil/arch/osx/process_info.h
deleted file mode 100644
index 08046bcb..00000000
--- a/psutil/arch/osx/process_info.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <Python.h>
-
-typedef struct kinfo_proc kinfo_proc;
-
-int psutil_is_zombie(pid_t pid);
-int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
-int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
-int psutil_proc_pidinfo(
- pid_t pid, int flavor, uint64_t arg, void *pti, int size);
-
-PyObject *psutil_proc_cmdline(PyObject *self, PyObject *args);
-PyObject *psutil_proc_environ(PyObject *self, PyObject *args);
diff --git a/setup.py b/setup.py
index 91b1ab14..54652aae 100755
--- a/setup.py
+++ b/setup.py
@@ -246,7 +246,6 @@ elif MACOS:
'psutil/arch/osx/mem.c',
'psutil/arch/osx/net.c',
'psutil/arch/osx/proc.c',
- 'psutil/arch/osx/process_info.c',
'psutil/arch/osx/sensors.c',
'psutil/arch/osx/sys.c',
],