summaryrefslogtreecommitdiff
path: root/psutil/_psutil_osx.c
diff options
context:
space:
mode:
Diffstat (limited to 'psutil/_psutil_osx.c')
-rw-r--r--psutil/_psutil_osx.c792
1 files changed, 6 insertions, 786 deletions
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
index 713f3d6c..30a5312e 100644
--- a/psutil/_psutil_osx.c
+++ b/psutil/_psutil_osx.c
@@ -12,33 +12,27 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
-#include <utmpx.h>
#include <sys/sysctl.h>
#include <libproc.h>
#include <sys/proc_info.h>
#include <netinet/tcp_fsm.h>
#include <arpa/inet.h>
-#include <net/if_dl.h>
#include <pwd.h>
#include <unistd.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
-
#include <mach-o/loader.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/IOBSD.h>
-#include <IOKit/ps/IOPowerSources.h>
-#include <IOKit/ps/IOPSKeys.h>
-
#include "_psutil_common.h"
#include "_psutil_posix.h"
-#include "arch/osx/process_info.h"
#include "arch/osx/cpu.h"
+#include "arch/osx/disk.h"
+#include "arch/osx/mem.h"
+#include "arch/osx/net.h"
+#include "arch/osx/process_info.h"
+#include "arch/osx/sensors.h"
+#include "arch/osx/sys.h"
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
@@ -47,28 +41,6 @@ static PyObject *ZombieProcessError;
/*
- * A wrapper around host_statistics() invoked with HOST_VM_INFO.
- */
-int
-psutil_sys_vminfo(vm_statistics_data_t *vmstat) {
- kern_return_t ret;
- mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t);
- mach_port_t mport = mach_host_self();
-
- ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)vmstat, &count);
- if (ret != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_VM_INFO) syscall failed: %s",
- mach_error_string(ret));
- return 0;
- }
- mach_port_deallocate(mach_task_self(), mport);
- return 1;
-}
-
-
-/*
* A wrapper around task_for_pid() which sucks big time:
* - it's not documented
* - errno is set only sometimes
@@ -499,350 +471,6 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) {
/*
- * Return system virtual memory stats.
- * See:
- * https://opensource.apple.com/source/system_cmds/system_cmds-790/
- * vm_stat.tproj/vm_stat.c.auto.html
- */
-static PyObject *
-psutil_virtual_mem(PyObject *self, PyObject *args) {
- int mib[2];
- uint64_t total;
- size_t len = sizeof(total);
- vm_statistics_data_t vm;
- long pagesize = psutil_getpagesize();
- // physical mem
- mib[0] = CTL_HW;
- mib[1] = HW_MEMSIZE;
-
- // This is also available as sysctlbyname("hw.memsize").
- if (sysctl(mib, 2, &total, &len, NULL, 0)) {
- if (errno != 0)
- PyErr_SetFromErrno(PyExc_OSError);
- else
- PyErr_Format(
- PyExc_RuntimeError, "sysctl(HW_MEMSIZE) syscall failed");
- return NULL;
- }
-
- // vm
- if (!psutil_sys_vminfo(&vm))
- return NULL;
-
- return Py_BuildValue(
- "KKKKKK",
- total,
- (unsigned long long) vm.active_count * pagesize, // active
- (unsigned long long) vm.inactive_count * pagesize, // inactive
- (unsigned long long) vm.wire_count * pagesize, // wired
- (unsigned long long) vm.free_count * pagesize, // free
- (unsigned long long) vm.speculative_count * pagesize // speculative
- );
-}
-
-
-/*
- * Return stats about swap memory.
- */
-static PyObject *
-psutil_swap_mem(PyObject *self, PyObject *args) {
- int mib[2];
- size_t size;
- struct xsw_usage totals;
- vm_statistics_data_t vmstat;
- long pagesize = psutil_getpagesize();
-
- mib[0] = CTL_VM;
- mib[1] = VM_SWAPUSAGE;
- size = sizeof(totals);
- if (sysctl(mib, 2, &totals, &size, NULL, 0) == -1) {
- if (errno != 0)
- PyErr_SetFromErrno(PyExc_OSError);
- else
- PyErr_Format(
- PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) syscall failed");
- return NULL;
- }
- if (!psutil_sys_vminfo(&vmstat))
- return NULL;
-
- return Py_BuildValue(
- "LLLKK",
- totals.xsu_total,
- totals.xsu_used,
- totals.xsu_avail,
- (unsigned long long)vmstat.pageins * pagesize,
- (unsigned long long)vmstat.pageouts * pagesize);
-}
-
-
-/*
- * Return a Python list of tuple representing per-cpu times
- */
-static PyObject *
-psutil_per_cpu_times(PyObject *self, PyObject *args) {
- natural_t cpu_count;
- natural_t i;
- processor_info_array_t info_array;
- mach_msg_type_number_t info_count;
- kern_return_t error;
- processor_cpu_load_info_data_t *cpu_load_info = NULL;
- int ret;
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_cputime = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- mach_port_t host_port = mach_host_self();
- error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO,
- &cpu_count, &info_array, &info_count);
- if (error != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_processor_info(PROCESSOR_CPU_LOAD_INFO) syscall failed: %s",
- mach_error_string(error));
- goto error;
- }
- mach_port_deallocate(mach_task_self(), host_port);
-
- cpu_load_info = (processor_cpu_load_info_data_t *) info_array;
-
- for (i = 0; i < cpu_count; i++) {
- py_cputime = Py_BuildValue(
- "(dddd)",
- (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK,
- (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
- (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
- (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
- );
- if (!py_cputime)
- goto error;
- if (PyList_Append(py_retlist, py_cputime))
- goto error;
- Py_CLEAR(py_cputime);
- }
-
- ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
- info_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
- return py_retlist;
-
-error:
- Py_XDECREF(py_cputime);
- Py_DECREF(py_retlist);
- if (cpu_load_info != NULL) {
- ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
- info_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
- }
- return NULL;
-}
-
-
-/*
- * Return a Python float indicating the system boot time expressed in
- * seconds since the epoch.
- */
-static PyObject *
-psutil_boot_time(PyObject *self, PyObject *args) {
- // fetch sysctl "kern.boottime"
- static int request[2] = { CTL_KERN, KERN_BOOTTIME };
- struct timeval result;
- size_t result_len = sizeof result;
- time_t boot_time = 0;
-
- if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1)
- return PyErr_SetFromErrno(PyExc_OSError);
- boot_time = result.tv_sec;
- return Py_BuildValue("f", (float)boot_time);
-}
-
-
-/*
- * Return a list of tuples including device, mount point and fs type
- * for all partitions mounted on the system.
- */
-static PyObject *
-psutil_disk_partitions(PyObject *self, PyObject *args) {
- int num;
- int i;
- int len;
- uint64_t flags;
- char opts[400];
- struct statfs *fs = NULL;
- PyObject *py_dev = NULL;
- PyObject *py_mountp = NULL;
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
-
- // get the number of mount points
- Py_BEGIN_ALLOW_THREADS
- num = getfsstat(NULL, 0, MNT_NOWAIT);
- Py_END_ALLOW_THREADS
- if (num == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- len = sizeof(*fs) * num;
- fs = malloc(len);
- if (fs == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- Py_BEGIN_ALLOW_THREADS
- num = getfsstat(fs, len, MNT_NOWAIT);
- Py_END_ALLOW_THREADS
- if (num == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- for (i = 0; i < num; i++) {
- opts[0] = 0;
- flags = fs[i].f_flags;
-
- // see sys/mount.h
- if (flags & MNT_RDONLY)
- strlcat(opts, "ro", sizeof(opts));
- else
- strlcat(opts, "rw", sizeof(opts));
- if (flags & MNT_SYNCHRONOUS)
- strlcat(opts, ",sync", sizeof(opts));
- if (flags & MNT_NOEXEC)
- strlcat(opts, ",noexec", sizeof(opts));
- if (flags & MNT_NOSUID)
- strlcat(opts, ",nosuid", sizeof(opts));
- if (flags & MNT_UNION)
- strlcat(opts, ",union", sizeof(opts));
- if (flags & MNT_ASYNC)
- strlcat(opts, ",async", sizeof(opts));
- if (flags & MNT_EXPORTED)
- strlcat(opts, ",exported", sizeof(opts));
- if (flags & MNT_QUARANTINE)
- strlcat(opts, ",quarantine", sizeof(opts));
- if (flags & MNT_LOCAL)
- strlcat(opts, ",local", sizeof(opts));
- if (flags & MNT_QUOTA)
- strlcat(opts, ",quota", sizeof(opts));
- if (flags & MNT_ROOTFS)
- strlcat(opts, ",rootfs", sizeof(opts));
- if (flags & MNT_DOVOLFS)
- strlcat(opts, ",dovolfs", sizeof(opts));
- if (flags & MNT_DONTBROWSE)
- strlcat(opts, ",dontbrowse", sizeof(opts));
- if (flags & MNT_IGNORE_OWNERSHIP)
- strlcat(opts, ",ignore-ownership", sizeof(opts));
- if (flags & MNT_AUTOMOUNTED)
- strlcat(opts, ",automounted", sizeof(opts));
- if (flags & MNT_JOURNALED)
- strlcat(opts, ",journaled", sizeof(opts));
- if (flags & MNT_NOUSERXATTR)
- strlcat(opts, ",nouserxattr", sizeof(opts));
- if (flags & MNT_DEFWRITE)
- strlcat(opts, ",defwrite", sizeof(opts));
- if (flags & MNT_MULTILABEL)
- strlcat(opts, ",multilabel", sizeof(opts));
- if (flags & MNT_NOATIME)
- strlcat(opts, ",noatime", sizeof(opts));
- if (flags & MNT_UPDATE)
- strlcat(opts, ",update", sizeof(opts));
- if (flags & MNT_RELOAD)
- strlcat(opts, ",reload", sizeof(opts));
- if (flags & MNT_FORCE)
- strlcat(opts, ",force", sizeof(opts));
- if (flags & MNT_CMDFLAGS)
- strlcat(opts, ",cmdflags", sizeof(opts));
-
- py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname);
- if (! py_dev)
- goto error;
- py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname);
- if (! py_mountp)
- goto error;
- py_tuple = Py_BuildValue(
- "(OOss)",
- py_dev, // device
- py_mountp, // mount point
- fs[i].f_fstypename, // fs type
- opts); // options
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_CLEAR(py_dev);
- Py_CLEAR(py_mountp);
- Py_CLEAR(py_tuple);
- }
-
- free(fs);
- return py_retlist;
-
-error:
- Py_XDECREF(py_dev);
- Py_XDECREF(py_mountp);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- if (fs != NULL)
- free(fs);
- return NULL;
-}
-
-
-static PyObject *
-psutil_disk_usage_used(PyObject *self, PyObject *args) {
- PyObject *py_default_value;
- PyObject *py_mount_point_bytes = NULL;
- char* mount_point;
-
-#if PY_MAJOR_VERSION >= 3
- if (!PyArg_ParseTuple(args, "O&O", PyUnicode_FSConverter, &py_mount_point_bytes, &py_default_value)) {
- return NULL;
- }
- mount_point = PyBytes_AsString(py_mount_point_bytes);
- if (NULL == mount_point) {
- Py_XDECREF(py_mount_point_bytes);
- return NULL;
- }
-#else
- if (!PyArg_ParseTuple(args, "sO", &mount_point, &py_default_value)) {
- return NULL;
- }
-#endif
-
-#ifdef ATTR_VOL_SPACEUSED
- /* Call getattrlist(ATTR_VOL_SPACEUSED) to get used space info. */
- int ret;
- struct {
- uint32_t size;
- uint64_t spaceused;
- } __attribute__((aligned(4), packed)) attrbuf = {0};
- struct attrlist attrs = {0};
-
- attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
- attrs.volattr = ATTR_VOL_INFO | ATTR_VOL_SPACEUSED;
- Py_BEGIN_ALLOW_THREADS
- ret = getattrlist(mount_point, &attrs, &attrbuf, sizeof(attrbuf), 0);
- Py_END_ALLOW_THREADS
- if (ret == 0) {
- Py_XDECREF(py_mount_point_bytes);
- return PyLong_FromUnsignedLongLong(attrbuf.spaceused);
- }
- psutil_debug("getattrlist(ATTR_VOL_SPACEUSED) failed, fall-back to default value");
-#endif
- Py_XDECREF(py_mount_point_bytes);
- Py_INCREF(py_default_value);
- return py_default_value;
-}
-
-/*
* Return process threads
*/
static PyObject *
@@ -1254,414 +882,6 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) {
/*
- * Return a Python list of named tuples with overall network I/O information
- */
-static PyObject *
-psutil_net_io_counters(PyObject *self, PyObject *args) {
- char *buf = NULL, *lim, *next;
- struct if_msghdr *ifm;
- int mib[6];
- mib[0] = CTL_NET; // networking subsystem
- mib[1] = PF_ROUTE; // type of information
- mib[2] = 0; // protocol (IPPROTO_xxx)
- mib[3] = 0; // address family
- mib[4] = NET_RT_IFLIST2; // operation
- mib[5] = 0;
- size_t len;
- PyObject *py_ifc_info = NULL;
- PyObject *py_retdict = PyDict_New();
-
- if (py_retdict == NULL)
- return NULL;
-
- if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- buf = malloc(len);
- if (buf == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- lim = buf + len;
-
- for (next = buf; next < lim; ) {
- ifm = (struct if_msghdr *)next;
- next += ifm->ifm_msglen;
-
- if (ifm->ifm_type == RTM_IFINFO2) {
- py_ifc_info = NULL;
- struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
- struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
- char ifc_name[32];
-
- strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen);
- ifc_name[sdl->sdl_nlen] = 0;
-
- py_ifc_info = Py_BuildValue(
- "(KKKKKKKi)",
- if2m->ifm_data.ifi_obytes,
- if2m->ifm_data.ifi_ibytes,
- if2m->ifm_data.ifi_opackets,
- if2m->ifm_data.ifi_ipackets,
- if2m->ifm_data.ifi_ierrors,
- if2m->ifm_data.ifi_oerrors,
- if2m->ifm_data.ifi_iqdrops,
- 0); // dropout not supported
-
- if (!py_ifc_info)
- goto error;
- if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
- goto error;
- Py_CLEAR(py_ifc_info);
- }
- else {
- continue;
- }
- }
-
- free(buf);
- return py_retdict;
-
-error:
- Py_XDECREF(py_ifc_info);
- Py_DECREF(py_retdict);
- if (buf != NULL)
- free(buf);
- return NULL;
-}
-
-
-/*
- * Return a Python dict of tuples for disk I/O information
- */
-static PyObject *
-psutil_disk_io_counters(PyObject *self, PyObject *args) {
- CFDictionaryRef parent_dict;
- CFDictionaryRef props_dict;
- CFDictionaryRef stats_dict;
- io_registry_entry_t parent;
- io_registry_entry_t disk;
- io_iterator_t disk_list;
- PyObject *py_disk_info = NULL;
- PyObject *py_retdict = PyDict_New();
-
- if (py_retdict == NULL)
- return NULL;
-
- // Get list of disks
- if (IOServiceGetMatchingServices(kIOMasterPortDefault,
- IOServiceMatching(kIOMediaClass),
- &disk_list) != kIOReturnSuccess) {
- PyErr_SetString(
- PyExc_RuntimeError, "unable to get the list of disks.");
- goto error;
- }
-
- // Iterate over disks
- while ((disk = IOIteratorNext(disk_list)) != 0) {
- py_disk_info = NULL;
- parent_dict = NULL;
- props_dict = NULL;
- stats_dict = NULL;
-
- if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent)
- != kIOReturnSuccess) {
- PyErr_SetString(PyExc_RuntimeError,
- "unable to get the disk's parent.");
- IOObjectRelease(disk);
- goto error;
- }
-
- if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
- if (IORegistryEntryCreateCFProperties(
- disk,
- (CFMutableDictionaryRef *) &parent_dict,
- kCFAllocatorDefault,
- kNilOptions
- ) != kIOReturnSuccess)
- {
- PyErr_SetString(PyExc_RuntimeError,
- "unable to get the parent's properties.");
- IOObjectRelease(disk);
- IOObjectRelease(parent);
- goto error;
- }
-
- if (IORegistryEntryCreateCFProperties(
- parent,
- (CFMutableDictionaryRef *) &props_dict,
- kCFAllocatorDefault,
- kNilOptions
- ) != kIOReturnSuccess)
- {
- PyErr_SetString(PyExc_RuntimeError,
- "unable to get the disk properties.");
- CFRelease(props_dict);
- IOObjectRelease(disk);
- IOObjectRelease(parent);
- goto error;
- }
-
- const int kMaxDiskNameSize = 64;
- CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue(
- parent_dict, CFSTR(kIOBSDNameKey));
- char disk_name[kMaxDiskNameSize];
-
- CFStringGetCString(disk_name_ref,
- disk_name,
- kMaxDiskNameSize,
- CFStringGetSystemEncoding());
-
- stats_dict = (CFDictionaryRef)CFDictionaryGetValue(
- props_dict, CFSTR(kIOBlockStorageDriverStatisticsKey));
-
- if (stats_dict == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "Unable to get disk stats.");
- goto error;
- }
-
- CFNumberRef number;
- int64_t reads = 0;
- int64_t writes = 0;
- int64_t read_bytes = 0;
- int64_t write_bytes = 0;
- int64_t read_time = 0;
- int64_t write_time = 0;
-
- // Get disk reads/writes
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsReadsKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &reads);
- }
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsWritesKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &writes);
- }
-
- // Get disk bytes read/written
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes);
- }
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes);
- }
-
- // Get disk time spent reading/writing (nanoseconds)
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &read_time);
- }
- if ((number = (CFNumberRef)CFDictionaryGetValue(
- stats_dict,
- CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey))))
- {
- CFNumberGetValue(number, kCFNumberSInt64Type, &write_time);
- }
-
- // Read/Write time on macOS comes back in nanoseconds and in psutil
- // we've standardized on milliseconds so do the conversion.
- py_disk_info = Py_BuildValue(
- "(KKKKKK)",
- reads,
- writes,
- read_bytes,
- write_bytes,
- read_time / 1000 / 1000,
- write_time / 1000 / 1000);
- if (!py_disk_info)
- goto error;
- if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info))
- goto error;
- Py_CLEAR(py_disk_info);
-
- CFRelease(parent_dict);
- IOObjectRelease(parent);
- CFRelease(props_dict);
- IOObjectRelease(disk);
- }
- }
-
- IOObjectRelease (disk_list);
-
- return py_retdict;
-
-error:
- Py_XDECREF(py_disk_info);
- Py_DECREF(py_retdict);
- return NULL;
-}
-
-
-/*
- * Return currently connected users as a list of tuples.
- */
-static PyObject *
-psutil_users(PyObject *self, PyObject *args) {
- struct utmpx *utx;
- PyObject *py_username = NULL;
- PyObject *py_tty = NULL;
- PyObject *py_hostname = NULL;
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
- while ((utx = getutxent()) != NULL) {
- if (utx->ut_type != USER_PROCESS)
- continue;
- py_username = PyUnicode_DecodeFSDefault(utx->ut_user);
- if (! py_username)
- goto error;
- py_tty = PyUnicode_DecodeFSDefault(utx->ut_line);
- if (! py_tty)
- goto error;
- py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host);
- if (! py_hostname)
- goto error;
- py_tuple = Py_BuildValue(
- "(OOOdi)",
- py_username, // username
- py_tty, // tty
- py_hostname, // hostname
- (double)utx->ut_tv.tv_sec, // start time
- utx->ut_pid // process id
- );
- if (!py_tuple) {
- endutxent();
- goto error;
- }
- if (PyList_Append(py_retlist, py_tuple)) {
- endutxent();
- goto error;
- }
- Py_CLEAR(py_username);
- Py_CLEAR(py_tty);
- Py_CLEAR(py_hostname);
- Py_CLEAR(py_tuple);
- }
-
- endutxent();
- return py_retlist;
-
-error:
- Py_XDECREF(py_username);
- Py_XDECREF(py_tty);
- Py_XDECREF(py_hostname);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- return NULL;
-}
-
-
-/*
- * Return battery information.
- */
-static PyObject *
-psutil_sensors_battery(PyObject *self, PyObject *args) {
- PyObject *py_tuple = NULL;
- CFTypeRef power_info = NULL;
- CFArrayRef power_sources_list = NULL;
- CFDictionaryRef power_sources_information = NULL;
- CFNumberRef capacity_ref = NULL;
- CFNumberRef time_to_empty_ref = NULL;
- CFStringRef ps_state_ref = NULL;
- uint32_t capacity; /* units are percent */
- int time_to_empty; /* units are minutes */
- int is_power_plugged;
-
- power_info = IOPSCopyPowerSourcesInfo();
-
- if (!power_info) {
- PyErr_SetString(PyExc_RuntimeError,
- "IOPSCopyPowerSourcesInfo() syscall failed");
- goto error;
- }
-
- power_sources_list = IOPSCopyPowerSourcesList(power_info);
- if (!power_sources_list) {
- PyErr_SetString(PyExc_RuntimeError,
- "IOPSCopyPowerSourcesList() syscall failed");
- goto error;
- }
-
- /* Should only get one source. But in practice, check for > 0 sources */
- if (!CFArrayGetCount(power_sources_list)) {
- PyErr_SetString(PyExc_NotImplementedError, "no battery");
- goto error;
- }
-
- power_sources_information = IOPSGetPowerSourceDescription(
- power_info, CFArrayGetValueAtIndex(power_sources_list, 0));
-
- capacity_ref = (CFNumberRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSCurrentCapacityKey));
- if (!CFNumberGetValue(capacity_ref, kCFNumberSInt32Type, &capacity)) {
- PyErr_SetString(PyExc_RuntimeError,
- "No battery capacity infomration in power sources info");
- goto error;
- }
-
- ps_state_ref = (CFStringRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSPowerSourceStateKey));
- is_power_plugged = CFStringCompare(
- ps_state_ref, CFSTR(kIOPSACPowerValue), 0)
- == kCFCompareEqualTo;
-
- time_to_empty_ref = (CFNumberRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSTimeToEmptyKey));
- if (!CFNumberGetValue(time_to_empty_ref,
- kCFNumberIntType, &time_to_empty)) {
- /* This value is recommended for non-Apple power sources, so it's not
- * an error if it doesn't exist. We'll return -1 for "unknown" */
- /* A value of -1 indicates "Still Calculating the Time" also for
- * apple power source */
- time_to_empty = -1;
- }
-
- py_tuple = Py_BuildValue("Iii",
- capacity, time_to_empty, is_power_plugged);
- if (!py_tuple) {
- goto error;
- }
-
- CFRelease(power_info);
- CFRelease(power_sources_list);
- /* Caller should NOT release power_sources_information */
-
- return py_tuple;
-
-error:
- if (power_info)
- CFRelease(power_info);
- if (power_sources_list)
- CFRelease(power_sources_list);
- Py_XDECREF(py_tuple);
- return NULL;
-}
-
-
-/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef mod_methods[] = {