/* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc2 p; char *ttname; int num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = KI_MAXCOMLEN; if (num >= sizeof(P->cmd)) { num = sizeof(P->cmd) - 1; } memcpy (P->cmd, p.p_comm, num); P->cmd[num] = '\0'; P->pid = p.p_pid; P->ppid = p.p_ppid; P->pgrp = p.p__pgid; P->session = p.p_sid; P->rss = p.p_vm_rssize; P->vsize = p.p_vm_dsize + p.p_vm_dsize + p.p_vm_ssize; /* XXX */ P->start_time = p.p_ustart_sec; P->wchan = (unsigned long) p.p_wchan; P->state = p.p_stat; P->nice = p.p_nice; P->flags = p.p_realflag; P->tpgid = p.p_tpgid; P->processor = p.p_cpuid; P->nlwp = p.p_nlwps; /* we like it Linux-encoded :-) */ tty_maj = major (p.p_tdev); tty_min = minor (p.p_tdev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof(P->tty_text), "%3d,%-3d", tty_maj, tty_min); if (p.p_tdev != NODEV && (ttname = devname (p.p_tdev, S_IFCHR)) != NULL) { memcpy (P->tty_text, ttname, sizeof(P->tty_text)); } if (p.p_tdev == NODEV) { /* XXXJDM nasty hack */ memcpy (P->tty_text, "/dev/ttyE4", sizeof(P->tty_text)); } if (P->pid != pid) { return FALSE; } return TRUE; }
/* * Return process controlling terminal number as an integer. */ static PyObject* get_process_tty_nr(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("i", kp.kp_eproc.e_tdev); }
/* * Return number of threads used by process as a Python integer. */ static PyObject* get_process_num_threads(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("l", (long)kp.ki_numthreads); }
/* * Return process name from kinfo_proc as a Python string. */ static PyObject* get_process_name(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("s", kp.ki_comm); }
/* * Return a Python float indicating the process create time expressed in * seconds since the epoch. */ static PyObject* get_process_create_time(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("d", TV2DOUBLE(kp.ki_start)); }
/* * Return process status as a Python integer. */ static PyObject* get_process_status(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("i", (int)kp.kp_proc.p_stat); }
/* * Return the RSS and VMS as a Python tuple. */ static PyObject* get_memory_info(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("(ll)", ptoa(kp.ki_rssize), (long)kp.ki_size); }
GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash = NULL; char **penv; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd; struct kinfo_proc p; int i; kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return NULL; } if (! get_kinfo_proc (pid, &p)) { g_warning ("get_kinfo_proc failed: %s", g_strerror (errno)); goto fail; } penv = kvm_getenvv (kd, &p, 0); if (penv == NULL) { g_warning ("kvm_getenvv failed: %s", kvm_geterr (kd)); goto fail; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; penv[i] != NULL; i++) { char **vals; if (!penv[i][0]) continue; vals = g_strsplit (penv[i], "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } fail: kvm_close (kd); return hash; }
/* * Return process real group id from ki_comm as a Python integer. */ static PyObject* get_process_gids(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_rgid, (long)kp.kp_eproc.e_ucred.cr_groups[0], (long)kp.kp_eproc.e_pcred.p_svgid); }
/* * Return a Python float indicating the process create time expressed in * seconds since the epoch. */ static PyObject* get_process_io_counters(PyObject* self, PyObject* args) { long pid; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } // there's apparently no way to determine bytes count, hence return -1. return Py_BuildValue("(llll)", kp.p_uru_inblock, kp.p_uru_oublock, -1, -1); }
/* * Return a Python tuple (user_time, kernel_time) */ static PyObject* get_cpu_times(PyObject* self, PyObject* args) { long pid; double user_t, sys_t; struct kinfo_proc kp; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } // convert from microseconds to seconds user_t = TV2DOUBLE(kp.ki_rusage.ru_utime); sys_t = TV2DOUBLE(kp.ki_rusage.ru_stime); return Py_BuildValue("(dd)", user_t, sys_t); }
uid_t ck_unix_pid_get_uid (pid_t pid) { uid_t uid; gboolean res; struct kinfo_proc p; g_return_val_if_fail (pid > 1, 0); uid = -1; res = get_kinfo_proc (pid, &p); if (res) { uid = p.p_uid; } return uid; }
struct psi_process * psi_arch_process(const pid_t pid) { struct kinfo_proc p; struct psi_process *proci; if (get_kinfo_proc(pid, &p) == -1) { return NULL; } proci = psi_calloc(sizeof(struct psi_process)); if (proci == NULL) { return NULL; } if (set_exe(proci, &p) == -1) goto cleanup; if (set_cwd(proci, &p) == -1) goto cleanup; if (set_kp_proc(proci, &p) == -1) goto cleanup; if (set_kp_eproc(proci, &p) == -1) goto cleanup; if (set_task(proci, &p) == -1) goto cleanup; if (proci->utime_status == PSI_STATUS_PRIVS || proci->stime_status == PSI_STATUS_PRIVS) proci->cputime_status = PSI_STATUS_PRIVS; else { proci->cputime = calc_cputime(proci->utime, proci->stime); proci->cputime_status = PSI_STATUS_OK; } if (proci->command_status == PSI_STATUS_PRIVS) { /* Ensure Process.command always has a value, as per our * contract with the user. */ proci->command = psi_strdup(""); proci->command_status = PSI_STATUS_OK; } return proci; cleanup: psi_free_process(proci); return NULL; }
/* * Return process current working directory. */ static PyObject* get_process_cwd(PyObject* self, PyObject* args) { long pid; PyObject *path = NULL; struct kinfo_file *freep, *kif; struct kinfo_proc kipp; int i, cnt; if (! PyArg_ParseTuple(args, "l", &pid)) return NULL; if (get_kinfo_proc(pid, &kipp) == -1) return NULL; freep = kinfo_getfile(pid, &cnt); if (freep == NULL) { PyErr_SetFromErrno(0); return NULL; } for (i = 0; i < cnt; i++) { kif = &freep[i]; if (kif->kf_fd == KF_FD_TYPE_CWD) { path = Py_BuildValue("s", kif->kf_path); break; } } /* * For lower pids it seems we can't retrieve any information * (lsof can't do that it either). Since this happens even * as root we return an empty string instead of AccessDenied. */ if (path == NULL) { path = Py_BuildValue("s", ""); } free(freep); return path; }
/* * Return files opened by process as a list of (path, fd) tuples */ static PyObject* get_process_open_files(PyObject* self, PyObject* args) { long pid; PyObject *retList = PyList_New(0); PyObject *tuple = NULL; struct kinfo_file *freep, *kif; struct kinfo_proc kipp; int i, cnt; if (! PyArg_ParseTuple(args, "l", &pid)) return NULL; if (get_kinfo_proc(pid, &kipp) == -1) return NULL; freep = kinfo_getfile(pid, &cnt); if (freep == NULL) { PyErr_SetFromErrno(0); return NULL; } for (i = 0; i < cnt; i++) { kif = &freep[i]; if ((kif->kf_type == KF_TYPE_VNODE) && (kif->kf_vnode_type == KF_VTYPE_VREG)) { tuple = Py_BuildValue("(si)", kif->kf_path, kif->kf_fd); PyList_Append(retList, tuple); Py_DECREF(tuple); } } free(freep); return retList; }
/* * Return a list of tuples for every process memory maps. * 'procstat' cmdline utility has been used as an example. */ static PyObject* get_process_memory_maps(PyObject* self, PyObject* args) { long pid; int ptrwidth; int i, cnt; char addr[30]; char perms[10]; const char *path; PyObject* retlist = PyList_New(0); // FIXME - read /usr/src/usr.sbin/procmap #if 0 struct kinfo_proc kp; struct kinfo_vmentry *freep, *kve; PyObject* pytuple = NULL; ptrwidth = 2*sizeof(void *); // NOTE: Get the PID from args. if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } // NOTE: Get the VM Map for this process. freep = kinfo_getvmmap(pid, &cnt); if (freep == NULL) { PyErr_SetString(PyExc_RuntimeError, "kinfo_getvmmap() failed"); return NULL; } for (i = 0; i < cnt; i++) { kve = &freep[i]; addr[0] = '\0'; perms[0] = '\0'; sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, ptrwidth, (uintmax_t)kve->kve_end); strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", sizeof(perms)); if (strlen(kve->kve_path) == 0) { switch (kve->kve_type) { case KVME_TYPE_NONE: path = "[none]"; break; case KVME_TYPE_DEFAULT: path = "[default]"; break; case KVME_TYPE_VNODE: path = "[vnode]"; break; case KVME_TYPE_SWAP: path = "[swap]"; break; case KVME_TYPE_DEVICE: path = "[device]"; break; case KVME_TYPE_PHYS: path = "[phys]"; break; case KVME_TYPE_DEAD: path = "[dead]"; break; case KVME_TYPE_SG: path = "[sg]"; break; case KVME_TYPE_UNKNOWN: path = "[unknown]"; break; default: path = "[?]"; break; } } else { path = kve->kve_path; } pytuple = Py_BuildValue("sssiiii", addr, // "start-end" address perms, // "rwx" permissions path, // path kve->kve_resident, // rss kve->kve_private_resident, // private kve->kve_ref_count, // ref count kve->kve_shadow_count // shadow count ); PyList_Append(retlist, pytuple); Py_XDECREF(pytuple); } free(freep); #endif return retlist; }
/* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc p; char *ttname; int num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = KI_MAXCOMLEN; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.p_comm, num); P->cmd[num] = '\0'; P->pid = p.p_pid; P->ppid = p.p_ppid; P->pgrp = p.p__pgid; P->session = p.p_sid; P->rss = p.p_vm_rssize; P->vsize = p.p_vm_dsize + p.p_vm_dsize + p.p_vm_ssize; /* XXX */ P->start_time = p.p_ustart_sec; P->wchan = (unsigned long) p.p_wchan; P->state = p.p_stat; P->nice = p.p_nice; P->flags = p.p_psflags; P->tpgid = p.p_tpgid; P->processor = p.p_cpuid; /* we like it Linux-encoded :-) */ tty_maj = major (p.p_tdev); tty_min = minor (p.p_tdev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); if (p.p_tdev != NODEV && (ttname = devname (p.p_tdev, S_IFCHR)) != NULL) { memcpy (P->tty_text, ttname, sizeof (P->tty_text)); } if (p.p_tdev == NODEV) { /* XXX how do we associate X with its tty? */ #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) memcpy (P->tty_text, "/dev/ttyC4", sizeof (P->tty_text)); #else memcpy (P->tty_text, "/dev/ttyC0", sizeof (P->tty_text)); #endif } if (P->pid != pid) { return FALSE; } return TRUE; }