/* * check_process_text * check [process] text (memory) * * in : pid * out : -1 if error * 0 if no match * 1 if match */ static int check_process_text(fdOpenInfoRef info, int pid) { int status; int buf_used; struct proc_regionwithpathinfo rwpi; if (info->flags & PROC_LISTPIDSPATH_PATH_IS_VOLUME) { // ask for first memory region that matches mountpoint buf_used = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO3, info->match_stat.st_dev, &rwpi, sizeof(rwpi)); if (buf_used <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { // if no more text information is available for this process. return 0; } return -1; } else if (buf_used < sizeof(rwpi)) { // if we didn't get enough information return -1; } status = check_file(info, &rwpi.prp_vip.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } } else { uint64_t a = 0; while (1) { // for all memory regions // processing next address buf_used = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO2, a, &rwpi, sizeof(rwpi)); if (buf_used <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { // if no more text information is available for this process. break; } return -1; } else if (buf_used < sizeof(rwpi)) { // if we didn't get enough information return -1; } status = check_file(info, &rwpi.prp_vip.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } a = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size; } } return 0; }
void slay_impl(pid_t *pids, int n, int sig, pid_t pid, int include_children) { int i, hit = 0; DEBUG_V("slay %d with signal %d", pid, sig); kill(pid, sig); for (i = 0; i < n; i++) { struct proc_bsdinfo info; CHECK(proc_pidinfo(pids[i], PROC_PIDTBSDINFO, 0, &info, sizeof info)); if (info.pbi_pid == pid) { if (info.pbi_status == SZOMB) { LOG_V("Not killing PID %d because it's already died (in state 'Z').", pid); } else { LOG_V("Kill PID %d (in state 0x%x) with signal %d", pid, info.pbi_status, sig); kill(pid, sig); } hit = 1; } if (include_children && (info.pbi_ppid == pid)) { if (info.pbi_status == SZOMB) { LOG_V("Not killing PID %d because it's already died (in state 'Z').", info.pbi_pid); } else slay_impl(pids, n, sig, info.pbi_pid, include_children); } } if (!hit) { LOG_V("PID %d was missing from the proc list (while sending signal %d)", pid, sig); } }
/* * check_process_text * check [process] text (memory) * * in : pid * out : -1 if error * 0 if no match * 1 if match */ static int check_process_text(fdOpenInfoRef info, int pid) { uint64_t a = 0; int status; while (1) { // for all memory regions int buf_used; struct proc_regionwithpathinfo rwpi; // processing next address buf_used = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, a, &rwpi, sizeof(rwpi)); if (buf_used <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { // if no more text information is available for this process. break; } return -1; } else if (buf_used < sizeof(rwpi)) { // if we didn't get enough information return -1; } status = check_file(info, &rwpi.prp_vip.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } a = rwpi.prp_prinfo.pri_address + rwpi.prp_prinfo.pri_size; } return 0; }
quint64 UtilObject::processTime() { static const pid_t pid = qApp->applicationPid(); struct proc_taskinfo info; if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &info, sizeof(info)) < 0) return 0; return info.pti_total_user/1000 + info.pti_total_system/1000; }
void tt_fs_status_dump_ntv(IN tt_u32_t flag) { pid_t pid; int size; struct proc_fdinfo *fdinfo; pid = getpid(); size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); if (size <= 0) { return; } fdinfo = (struct proc_fdinfo *)malloc(size); if (fdinfo == NULL) { return; } size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo, size); if (size > 0) { int n, i; n = size / PROC_PIDLISTFD_SIZE; for (i = 0; i < n; ++i) { if (fdinfo[i].proc_fdtype == PROX_FDTYPE_VNODE) { struct vnode_fdinfowithpath vi; int vs = proc_pidfdinfo(pid, fdinfo[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vi, PROC_PIDFDVNODEPATHINFO_SIZE); if (vs == PROC_PIDFDVNODEPATHINFO_SIZE) { tt_printf("%s[fd: %d] [%s]\n", TT_COND(flag & TT_FS_STATUS_PREFIX, "<<FS>> ", ""), fdinfo[i].proc_fd, vi.pvip.vip_path); } } } } free(fdinfo); }
int get_proc_threadinfo (pid_t pid, uint64_t thread_handle, struct proc_threadinfo *pth) { pth->pth_name[0] = '\0'; int ret = proc_pidinfo (pid, PROC_PIDTHREADINFO, thread_handle, pth, sizeof (struct proc_threadinfo)); if (ret != 0) return 1; else return 0; }
void genOpenDescriptors(int pid, descriptor_type type, QueryData& results) { int bufsize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0); if (bufsize == -1) { VLOG(1) << "Could not list descriptors for pid: " << pid; return; } // Allocate structs for each descriptor. std::vector<proc_fdinfo> fds(bufsize / PROC_PIDLISTFD_SIZE); proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds.data(), bufsize); for (auto fd_info : fds) { if (type == DESCRIPTORS_TYPE_VNODE && fd_info.proc_fdtype == PROX_FDTYPE_VNODE) { genFileDescriptor(pid, fd_info.proc_fd, results); } else if (type == DESCRIPTORS_TYPE_SOCKET && fd_info.proc_fdtype == PROX_FDTYPE_SOCKET) { genSocketDescriptor(pid, fd_info.proc_fd, results); } } }
int find_fd_for_pid(pid_t pid, int *fd_list, int max_fd) { int count = 0; int bufferSize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0); struct stat stat_buf; if (bufferSize < 0) { printf("Error :/, cannot proc_pidinfo\n"); return 0; } struct proc_fdinfo *procFDInfo = (struct proc_fdinfo *)malloc(bufferSize); proc_pidinfo(pid, PROC_PIDLISTFDS, 0, procFDInfo, bufferSize); int numberOfProcFDs = bufferSize / PROC_PIDLISTFD_SIZE; int i; for(i = 0; i < numberOfProcFDs; i++) { if(procFDInfo[i].proc_fdtype == PROX_FDTYPE_VNODE) { struct vnode_fdinfowithpath vnodeInfo; proc_pidfdinfo(pid, procFDInfo[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE); if (stat(vnodeInfo.pvip.vip_path, &stat_buf) < 0) { if (flag_debug) perror("sstat"); continue; } if (!S_ISREG(stat_buf.st_mode) && !S_ISBLK(stat_buf.st_mode)) continue; if (is_ignored_file(vnodeInfo.pvip.vip_path)) continue; // OK, we've found a potential interesting file. fd_list[count++] = procFDInfo[i].proc_fd; //~ printf("[debug] %s\n",vnodeInfo.pvip.vip_path); if(count == max_fd) break; } } return count; }
inline bool getProcCred(int pid, proc_cred &cred) { struct proc_bsdshortinfo bsdinfo; if (proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0, &bsdinfo, sizeof(bsdinfo)) == sizeof(bsdinfo)) { cred.real.uid = bsdinfo.pbsi_ruid; cred.real.gid = bsdinfo.pbsi_ruid; cred.effective.uid = bsdinfo.pbsi_uid; cred.effective.gid = bsdinfo.pbsi_gid; return true; } return false; }
inline bool getProcCred(int pid, proc_cred& cred) { struct proc_bsdinfo bsdinfo; struct proc_bsdshortinfo bsdinfo_short; if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 1, &bsdinfo, PROC_PIDTBSDINFO_SIZE) == PROC_PIDTBSDINFO_SIZE) { cred.parent = bsdinfo.pbi_ppid; cred.group = bsdinfo.pbi_pgid; cred.status = bsdinfo.pbi_status; cred.nice = bsdinfo.pbi_nice; cred.real.uid = bsdinfo.pbi_ruid; cred.real.gid = bsdinfo.pbi_rgid; cred.effective.uid = bsdinfo.pbi_uid; cred.effective.gid = bsdinfo.pbi_gid; cred.saved.uid = bsdinfo.pbi_svuid; cred.saved.gid = bsdinfo.pbi_svgid; return true; } else if (proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 1, &bsdinfo_short, PROC_PIDT_SHORTBSDINFO_SIZE) == PROC_PIDT_SHORTBSDINFO_SIZE) { cred.parent = bsdinfo_short.pbsi_ppid; cred.group = bsdinfo_short.pbsi_pgid; cred.status = bsdinfo_short.pbsi_status; cred.real.uid = bsdinfo_short.pbsi_ruid; cred.real.gid = bsdinfo_short.pbsi_rgid; cred.effective.uid = bsdinfo_short.pbsi_uid; cred.effective.gid = bsdinfo_short.pbsi_gid; cred.saved.uid = bsdinfo_short.pbsi_svuid; cred.saved.gid = bsdinfo_short.pbsi_svgid; return true; } return false; }
char * osdep_get_cwd(pid_t pid) { static char wd[PATH_MAX]; struct proc_vnodepathinfo pathinfo; int ret; ret = proc_pidinfo( pid, PROC_PIDVNODEPATHINFO, 0, &pathinfo, sizeof pathinfo); if (ret == sizeof pathinfo) { strlcpy(wd, pathinfo.pvi_cdir.vip_path, sizeof wd); return (wd); } return (NULL); }
bool iszombie(pid_t p) { int ret; struct proc_bsdshortinfo bsdinfo; ret = proc_pidinfo(p, PROC_PIDT_SHORTBSDINFO, 1, &bsdinfo, sizeof(bsdinfo)); if (ret != sizeof(bsdinfo)) { return false; } if (bsdinfo.pbsi_status == SZOMB) { return true; } else { return false; } }
char * osdep_get_name(int fd, __unused char *tty) { struct proc_bsdinfo bsdinfo; pid_t pgrp; int ret; if ((pgrp = tcgetpgrp(fd)) == -1) return (NULL); ret = proc_pidinfo(pgrp, PROC_PIDTBSDINFO, 0, &bsdinfo, sizeof bsdinfo); if (ret == sizeof bsdinfo && *bsdinfo.pbi_comm != '\0') return (strdup(bsdinfo.pbi_comm)); return (NULL); }
static void close_all_fds() { #if HAVE_FDWALK fdwalk(fdwalker_close, NULL); #elif defined(linux) || defined(__linux) || defined(__linux__) char path[PATH_MAX]; DIR *root; struct dirent *de, *entry; int size = 0; snprintf(path, sizeof(path), "/proc/%d/fd", getpid()); #ifdef _PC_NAME_MAX size = pathconf(path, _PC_NAME_MAX); #endif size = MAX(size, PATH_MAX + 128); de = alloca(size); close(3); /* hoping opendir uses 3 */ root = opendir(path); if(!root) return; while(portable_readdir_r(root, de, &entry) == 0 && entry != NULL) { if(entry->d_name[0] >= '1' && entry->d_name[0] <= '9') { int tgt; tgt = atoi(entry->d_name); if(tgt != 3) close(tgt); } } close(3); #elif defined(__MACH__) && defined(__APPLE__) struct proc_fdinfo files[1024*16]; int rv, i = 0; rv = proc_pidinfo(getpid(), PROC_PIDLISTFDS, 0, files, sizeof(files)); if(rv > 0 && (rv % sizeof(files[0])) == 0) { rv /= sizeof(files[0]); for(i=0;i<rv;i++) { (void) close(files[i].proc_fd); } } #else struct rlimit rl; int i, reasonable_max; getrlimit(RLIMIT_NOFILE, &rl); reasonable_max = MIN(1<<14, rl.rlim_max); for (i = 0; i < reasonable_max; i++) (void) close(i); #endif }
void genProcRootAndCWD(int pid, Row &r) { r["cwd"] = ""; r["root"] = ""; struct proc_vnodepathinfo pathinfo; if (proc_pidinfo( pid, PROC_PIDVNODEPATHINFO, 0, &pathinfo, sizeof(pathinfo)) == sizeof(pathinfo)) { if (pathinfo.pvi_cdir.vip_vi.vi_stat.vst_dev != 0) { r["cwd"] = std::string(pathinfo.pvi_cdir.vip_path); } if (pathinfo.pvi_rdir.vip_vi.vi_stat.vst_dev != 0) { r["root"] = std::string(pathinfo.pvi_rdir.vip_path); } } }
static int getProcessInfo(RTPROCESS process, struct proc_taskinfo *tinfo) { LogAleksey(("getProcessInfo() getting info for %d", process)); int nb = proc_pidinfo(process, PROC_PIDTASKINFO, 0, tinfo, sizeof(*tinfo)); if (nb <= 0) { int rc = errno; Log(("proc_pidinfo() -> %s", strerror(rc))); return RTErrConvertFromDarwin(rc); } else if ((unsigned int)nb < sizeof(*tinfo)) { Log(("proc_pidinfo() -> too few bytes %d", nb)); return VERR_INTERNAL_ERROR; } return VINF_SUCCESS; }
bool LibProc::GetProcessInfo(ProcessId pid, ProcessInfo &info) { int res; struct proc_taskallinfo ti; res = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &ti, sizeof(ti)); if (res <= 0) return false; info.pid = pid; info.parentPid = ti.pbsd.pbi_ppid; info.realUid = ti.pbsd.pbi_ruid; info.effectiveUid = ti.pbsd.pbi_uid; info.realGid = ti.pbsd.pbi_rgid; info.effectiveGid = ti.pbsd.pbi_svgid; info.name = std::string(ti.pbsd.pbi_comm); return true; }
/* * Return process open files as a Python tuple. * References: * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd * - /usr/include/sys/proc_info.h */ static PyObject* get_process_open_files(PyObject* self, PyObject* args) { long pid; int pidinfo_result; int iterations; int i; int nb; struct proc_fdinfo *fds_pointer; struct proc_fdinfo *fdp_pointer; struct vnode_fdinfowithpath vi; PyObject *retList = PyList_New(0); PyObject *tuple = NULL; if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); if (pidinfo_result <= 0) { goto error; } fds_pointer = malloc(pidinfo_result); pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); free(fds_pointer); if (pidinfo_result <= 0) { goto error; } iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); for (i = 0; i < iterations; i++) { fdp_pointer = &fds_pointer[i]; // if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE) { nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, PROC_PIDFDVNODEPATHINFO, &vi, sizeof(vi)); // --- errors checking if (nb <= 0) { if ((errno == ENOENT) || (errno == EBADF)) { // no such file or directory or bad file descriptor; // let's assume the file has been closed or removed continue; } if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } else return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed"); } if (nb < sizeof(vi)) { return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)"); } // --- /errors checking // --- construct python list tuple = Py_BuildValue("(si)", vi.pvip.vip_path, (int)fdp_pointer->proc_fd); PyList_Append(retList, tuple); Py_DECREF(tuple); // --- /construct python list } } return retList; error: if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } else if (! pid_exists(pid) ) { return NoSuchProcess(); } else { return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDLISTFDS) failed"); } }
/* * Return process TCP and UDP connections as a list of tuples. * References: * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0 * - /usr/include/sys/proc_info.h */ static PyObject* get_process_connections(PyObject* self, PyObject* args) { long pid; int pidinfo_result; int iterations; int i; int nb; struct proc_fdinfo *fds_pointer; struct proc_fdinfo *fdp_pointer; struct socket_fdinfo si; PyObject *retList = PyList_New(0); PyObject *tuple = NULL; PyObject *laddr = NULL; PyObject *raddr = NULL; PyObject *af_filter = NULL; PyObject *type_filter = NULL; if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) { return NULL; } if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); return NULL; } if (pid == 0) { return retList; } pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); if (pidinfo_result <= 0) { goto error; } fds_pointer = malloc(pidinfo_result); pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); free(fds_pointer); if (pidinfo_result <= 0) { goto error; } iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); for (i = 0; i < iterations; i++) { errno = 0; fdp_pointer = &fds_pointer[i]; // if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) { nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, PROC_PIDFDSOCKETINFO, &si, sizeof(si)); // --- errors checking if (nb <= 0) { if (errno == EBADF) { // let's assume socket has been closed continue; } if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } else { return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed"); } } if (nb < sizeof(si)) { return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)"); } // --- /errors checking // int fd, family, type, lport, rport; char lip[200], rip[200]; char *state; int inseq; PyObject* _family; PyObject* _type; fd = (int)fdp_pointer->proc_fd; family = si.psi.soi_family; type = si.psi.soi_kind; if (type == 2) { type = SOCK_STREAM; } else if (type == 1) { type = SOCK_DGRAM; } else { continue; } // apply filters _family = PyLong_FromLong((long)family); inseq = PySequence_Contains(af_filter, _family); Py_DECREF(_family); if (inseq == 0) { continue; } _type = PyLong_FromLong((long)type); inseq = PySequence_Contains(type_filter, _type); Py_DECREF(_type); if (inseq == 0) { continue; } if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } if (family == AF_INET) { inet_ntop(AF_INET, &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4, lip, sizeof(lip)); inet_ntop(AF_INET, &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4, rip, sizeof(lip)); } else { inet_ntop(AF_INET6, &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6, lip, sizeof(lip)); inet_ntop(AF_INET6, &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6, lip, sizeof(rip)); } // check for inet_ntop failures if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); if (type == SOCK_STREAM) { state = get_connection_status((int)si.psi.soi_proto.pri_tcp.tcpsi_state); } else { state = ""; } laddr = Py_BuildValue("(si)", lip, lport); if (rport != 0) { raddr = Py_BuildValue("(si)", rip, rport); } else { raddr = PyTuple_New(0); } // --- construct python list tuple = Py_BuildValue("(iiiNNs)", fd, family, type, laddr, raddr, state); PyList_Append(retList, tuple); Py_DECREF(tuple); // --- /construct python list } } return retList; error: if (errno != 0) { return PyErr_SetFromErrno(PyExc_OSError); } else if (! pid_exists(pid) ) { return NoSuchProcess(); } else { return PyErr_Format(PyExc_RuntimeError, "proc_pidinfo(PROC_PIDLISTFDS) failed"); } }
/* * check_process_fds * check [process] open file descriptors * * in : pid * out : -1 if error * 0 if no match * 1 if match */ static int check_process_fds(fdOpenInfoRef info, int pid) { int buf_used; int i; int status; // get list of open file descriptors buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); if (buf_used <= 0) { return -1; } while (1) { if (buf_used > info->fds_size) { // if we need to allocate [more] space while (buf_used > info->fds_size) { info->fds_size += (sizeof(struct proc_fdinfo) * 32); } if (info->fds == NULL) { info->fds = malloc(info->fds_size); } else { info->fds = reallocf(info->fds, info->fds_size); } if (info->fds == NULL) { return -1; } } buf_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info->fds, (int)info->fds_size); if (buf_used <= 0) { return -1; } if ((buf_used + sizeof(struct proc_fdinfo)) >= info->fds_size) { // if not enough room in the buffer for an extra fd buf_used = (int)(info->fds_size + sizeof(struct proc_fdinfo)); continue; } info->fds_count = (int)(buf_used / sizeof(struct proc_fdinfo)); break; } // iterate through each file descriptor for (i = 0; i < info->fds_count; i++) { struct proc_fdinfo *fdp; fdp = &info->fds[i]; switch (fdp->proc_fdtype) { case PROX_FDTYPE_VNODE : { int buf_used; struct vnode_fdinfo vi; buf_used = proc_pidfdinfo(pid, fdp->proc_fd, PROC_PIDFDVNODEINFO, &vi, sizeof(vi)); if (buf_used <= 0) { if (errno == ENOENT) { /* * The file descriptor's vnode may have been revoked. This is a * bit of a hack, since an ENOENT error might not always mean the * descriptor's vnode has been revoked. As the libproc API * matures, this code may need to be revisited. */ continue; } return -1; } else if (buf_used < sizeof(vi)) { // if we didn't get enough information return -1; } if ((info->flags & PROC_LISTPIDSPATH_EXCLUDE_EVTONLY) && (vi.pfi.fi_openflags & O_EVTONLY)) { // if this file should be excluded continue; } status = check_file(info, &vi.pvi.vi_stat); if (status != 0) { // if error or match return status; } break; } default : break; } } return 0; }
/* * check_process_threads * check [process] thread working directories * * in : pid * out : -1 if error * 0 if no match * 1 if match */ static int check_process_threads(fdOpenInfoRef info, int pid) { int buf_used; int status; struct proc_taskallinfo tai; buf_used = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai)); if (buf_used <= 0) { if (errno == ESRCH) { // if the process is gone return 0; } return -1; } else if (buf_used < sizeof(tai)) { // if we didn't get enough information return -1; } // check thread info if (tai.pbsd.pbi_flags & PROC_FLAG_THCWD) { int i; // get list of threads buf_used = tai.ptinfo.pti_threadnum * sizeof(uint64_t); while (1) { if (buf_used > info->thr_size) { // if we need to allocate [more] space while (buf_used > info->thr_size) { info->thr_size += (sizeof(uint64_t) * 32); } if (info->threads == NULL) { info->threads = malloc(info->thr_size); } else { info->threads = reallocf(info->threads, info->thr_size); } if (info->threads == NULL) { return -1; } } buf_used = proc_pidinfo(pid, PROC_PIDLISTTHREADS, 0, info->threads, (int)info->thr_size); if (buf_used <= 0) { return -1; } if ((buf_used + sizeof(uint64_t)) >= info->thr_size) { // if not enough room in the buffer for an extra thread buf_used = (int)(info->thr_size + sizeof(uint64_t)); continue; } info->thr_count = buf_used / sizeof(uint64_t); break; } // iterate through each thread for (i = 0; i < info->thr_count; i++) { uint64_t thr = info->threads[i]; struct proc_threadwithpathinfo tpi; buf_used = proc_pidinfo(pid, PROC_PIDTHREADPATHINFO, thr, &tpi, sizeof(tpi)); if (buf_used <= 0) { if ((errno == ESRCH) || (errno == EINVAL)) { // if the process or thread is gone continue; } } else if (buf_used < sizeof(tai)) { // if we didn't get enough information return -1; } status = check_file(info, &tpi.pvip.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } } } return 0; }
QueryData genProcesses(QueryContext& context) { QueryData results; // Initialize time conversions. static mach_timebase_info_data_t time_base; if (time_base.denom == 0) { mach_timebase_info(&time_base); } auto pidlist = getProcList(context); int argmax = genMaxArgs(); for (auto& pid : pidlist) { Row r; r["pid"] = INTEGER(pid); { // The command line invocation including arguments. auto args = getProcRawArgs(pid, argmax); std::string cmdline = boost::algorithm::join(args.args, " "); r["cmdline"] = cmdline; } // The process relative root and current working directory. genProcRootAndCWD(pid, r); proc_cred cred; if (getProcCred(pid, cred)) { r["parent"] = BIGINT(cred.parent); r["pgroup"] = BIGINT(cred.group); // check if process state is one of the expected ones r["state"] = (1 <= cred.status && cred.status <= 5) ? TEXT(kProcessStateMapping[cred.status]) : TEXT('?'); r["nice"] = INTEGER(cred.nice); r["uid"] = BIGINT(cred.real.uid); r["gid"] = BIGINT(cred.real.gid); r["euid"] = BIGINT(cred.effective.uid); r["egid"] = BIGINT(cred.effective.gid); r["suid"] = BIGINT(cred.saved.uid); r["sgid"] = BIGINT(cred.saved.gid); } else { continue; } // If the process is not a Zombie, try to find the path and name. if (cred.status != 5) { r["path"] = getProcPath(pid); // OS X proc_name only returns 16 bytes, use the basename of the path. r["name"] = fs::path(r["path"]).filename().string(); } else { r["path"] = ""; std::vector<char> name(17); proc_name(pid, name.data(), 16); r["name"] = std::string(name.data()); } // If the path of the executable that started the process is available and // the path exists on disk, set on_disk to 1. If the path is not // available, set on_disk to -1. If, and only if, the path of the // executable is available and the file does NOT exist on disk, set on_disk // to 0. if (r["path"].empty()) { r["on_disk"] = INTEGER(-1); } else if (pathExists(r["path"])) { r["on_disk"] = INTEGER(1); } else { r["on_disk"] = INTEGER(0); } // systems usage and time information struct rusage_info_v2 rusage_info_data; int status = proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*)&rusage_info_data); // proc_pid_rusage returns -1 if it was unable to gather information if (status == 0) { // size/memory information r["wired_size"] = TEXT(rusage_info_data.ri_wired_size); r["resident_size"] = TEXT(rusage_info_data.ri_resident_size); r["total_size"] = TEXT(rusage_info_data.ri_phys_footprint); // time information r["user_time"] = TEXT(rusage_info_data.ri_user_time / CPU_TIME_RATIO); r["system_time"] = TEXT(rusage_info_data.ri_system_time / CPU_TIME_RATIO); // Convert the time in CPU ticks since boot to seconds. // This is relative to time not-sleeping since boot. r["start_time"] = TEXT((rusage_info_data.ri_proc_start_abstime / START_TIME_RATIO) * time_base.numer / time_base.denom); } else { r["wired_size"] = "-1"; r["resident_size"] = "-1"; r["total_size"] = "-1"; r["user_time"] = "-1"; r["system_time"] = "-1"; r["start_time"] = "-1"; } struct proc_taskinfo task_info; status = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info)); if (status == sizeof(task_info)) { r["threads"] = INTEGER(task_info.pti_threadnum); } else { r["threads"] = "-1"; } results.push_back(r); } return results; }
/** * Read all processes to initialize the information tree. * @param reference reference of ProcessTree * @param pflags Process engine flags * @return treesize > 0 if succeeded otherwise 0 */ int initprocesstree_sysdep(ProcessTree_T **reference, ProcessEngine_Flags pflags) { size_t pinfo_size = 0; int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; if (sysctl(mib, 4, NULL, &pinfo_size, NULL, 0) < 0) { LogError("system statistic error -- sysctl failed: %s\n", STRERROR); return 0; } struct kinfo_proc *pinfo = CALLOC(1, pinfo_size); if (sysctl(mib, 4, pinfo, &pinfo_size, NULL, 0)) { FREE(pinfo); LogError("system statistic error -- sysctl failed: %s\n", STRERROR); return 0; } size_t treesize = pinfo_size / sizeof(struct kinfo_proc); ProcessTree_T *pt = CALLOC(sizeof(ProcessTree_T), treesize); char *args = NULL; StringBuffer_T cmdline = NULL; if (pflags & ProcessEngine_CollectCommandLine) { cmdline = StringBuffer_create(64); args = CALLOC(1, systeminfo.argmax + 1); } for (int i = 0; i < treesize; i++) { pt[i].uptime = systeminfo.time / 10. - pinfo[i].kp_proc.p_starttime.tv_sec; pt[i].zombie = pinfo[i].kp_proc.p_stat == SZOMB ? true : false; pt[i].pid = pinfo[i].kp_proc.p_pid; pt[i].ppid = pinfo[i].kp_eproc.e_ppid; pt[i].cred.uid = pinfo[i].kp_eproc.e_pcred.p_ruid; pt[i].cred.euid = pinfo[i].kp_eproc.e_ucred.cr_uid; pt[i].cred.gid = pinfo[i].kp_eproc.e_pcred.p_rgid; if (pflags & ProcessEngine_CollectCommandLine) { size_t size = systeminfo.argmax; mib[0] = CTL_KERN; mib[1] = KERN_PROCARGS2; mib[2] = pt[i].pid; if (sysctl(mib, 3, args, &size, NULL, 0) != -1) { /* KERN_PROCARGS2 sysctl() returns following pseudo structure: * struct { * int argc * char execname[]; * char argv[argc][]; * char env[][]; * } * The strings are terminated with '\0' and may have variable '\0' padding */ int argc = *args; char *p = args + sizeof(int); // arguments beginning StringBuffer_clear(cmdline); p += strlen(p); // skip exename while (argc && p < args + systeminfo.argmax) { if (*p == 0) { // skip terminating 0 and variable length 0 padding p++; continue; } StringBuffer_append(cmdline, argc-- ? "%s " : "%s", p); p += strlen(p); } if (StringBuffer_length(cmdline)) pt[i].cmdline = Str_dup(StringBuffer_toString(StringBuffer_trim(cmdline))); } if (! pt[i].cmdline || ! *pt[i].cmdline) { FREE(pt[i].cmdline); pt[i].cmdline = Str_dup(pinfo[i].kp_proc.p_comm); } } if (! pt[i].zombie) { struct proc_taskinfo tinfo; int rv = proc_pidinfo(pt[i].pid, PROC_PIDTASKINFO, 0, &tinfo, sizeof(tinfo)); // If the process is zombie, skip this if (rv <= 0) { if (errno != EPERM) DEBUG("proc_pidinfo for pid %d failed -- %s\n", pt[i].pid, STRERROR); } else if (rv < sizeof(tinfo)) { LogError("proc_pidinfo for pid %d -- invalid result size\n", pt[i].pid); } else { pt[i].memory.usage = (uint64_t)tinfo.pti_resident_size; pt[i].cpu.time = (double)(tinfo.pti_total_user + tinfo.pti_total_system) / 100000000.; // The time is in nanoseconds, we store it as 1/10s pt[i].threads = tinfo.pti_threadnum; } } } if (pflags & ProcessEngine_CollectCommandLine) { StringBuffer_free(&cmdline); FREE(args); } FREE(pinfo); *reference = pt; return (int)treesize; }
JNIEXPORT jlong JNICALL Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount (JNIEnv *env, jobject mbean) { #ifdef __APPLE__ // This code is influenced by the darwin lsof source pid_t my_pid; struct proc_bsdinfo bsdinfo; struct proc_fdinfo *fds; int nfiles; kern_return_t kres; int res; size_t fds_size; kres = pid_for_task(mach_task_self(), &my_pid); if (res != KERN_SUCCESS) { throw_internal_error(env, "pid_for_task failed"); return -1; } // get the maximum number of file descriptors res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE); if (res <= 0) { throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed"); return -1; } // allocate memory to hold the fd information (we don't acutally use this information // but need it to get the number of open files) fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo); fds = malloc(fds_size); if (fds == NULL) { JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors"); return -1; } // get the list of open files - the return value is the number of bytes // proc_pidinfo filled in res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size); if (res <= 0) { free(fds); throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS"); return -1; } nfiles = res / sizeof(struct proc_fdinfo); free(fds); return nfiles; #elif defined(_ALLBSD_SOURCE) /* * XXXBSD: there's no way available to do it in FreeBSD, AFAIK. */ // throw_internal_error(env, "Unimplemented in FreeBSD"); return (100); #else /* solaris/linux */ DIR *dirp; struct dirent dbuf; struct dirent* dentp; jlong fds = 0; dirp = opendir("/proc/self/fd"); if (dirp == NULL) { throw_internal_error(env, "Unable to open directory /proc/self/fd"); return -1; } // iterate through directory entries, skipping '.' and '..' // each entry represents an open file descriptor. while ((dentp = read_dir(dirp, &dbuf)) != NULL) { if (isdigit(dentp->d_name[0])) { fds++; } } closedir(dirp); // subtract by 1 which was the fd open for this implementation return (fds - 1); #endif }
int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; size_t buf_size, mib_size = sizeof(mib)/sizeof(mib[0]); struct kinfo_proc *processes = NULL; struct proc_taskallinfo taskinfo; netsnmp_swrun_entry *entry; int rc, num_entries, i; DEBUGMSGTL(("swrun:load:arch"," load\n")); /* * get size to allocate. This introduces a bit of a race condition, * as the size could change between this call and the next... */ rc = sysctl(mib, mib_size, NULL, &buf_size, NULL, 0); if (rc < 0) { snmp_log(LOG_ERR, "KERN_PROC_ALL size sysctl failed: %d\n", rc); return -1; } processes = (struct kinfo_proc*) malloc(buf_size); if (NULL == processes) { snmp_log(LOG_ERR, "malloc failed\n"); return -1; } rc = sysctl(mib, mib_size, processes, &buf_size, NULL, 0); if (rc < 0) { snmp_log(LOG_ERR, "KERN_PROC_ALL sysctl failed: %d\n", rc); free(processes); return -1; } num_entries = buf_size / sizeof(struct kinfo_proc); for (i = 0; i < num_entries; i++) { /* * skip empty names. * p_stat = (SIDL|SRUN|SSLEEP|SSTOP|SZOMB) */ if (('\0' == processes[i].kp_proc.p_comm[0]) || (0 == processes[i].kp_proc.p_pid)) { DEBUGMSGTL(("swrun:load:arch", " skipping p_comm '%s', pid %5d, p_pstat %d\n", processes[i].kp_proc.p_comm ? processes[i].kp_proc.p_comm : "NULL", processes[i].kp_proc.p_pid, processes[i].kp_proc.p_stat)); continue; } DEBUGMSGTL(("swrun:load:arch"," %s pid %5d\n", processes[i].kp_proc.p_comm, processes[i].kp_proc.p_pid)); entry = netsnmp_swrun_entry_create(processes[i].kp_proc.p_pid); if (NULL == entry) continue; /* error already logged by function */ rc = CONTAINER_INSERT(container, entry); /* * p_comm is a partial name, but it is all we have at this point. */ entry->hrSWRunName_len = snprintf(entry->hrSWRunName, sizeof(entry->hrSWRunName)-1, "%s", processes[i].kp_proc.p_comm); /** sysctl for name, path, params */ rc = _set_command_name(entry); /* * map p_stat to RunStatus. Odd that there is no 'running' status. */ switch(processes[i].kp_proc.p_stat) { case SRUN: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; break; case SSLEEP: case SSTOP: entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; break; case SIDL: case SZOMB: default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; break; } /* * check for system processes */ if (P_SYSTEM & processes[i].kp_proc.p_flag) { entry->hrSWRunType = HRSWRUNTYPE_OPERATINGSYSTEM; DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "SYSTEM\n")); } else entry->hrSWRunType = HRSWRUNTYPE_APPLICATION; /* * get mem size, run time */ rc = proc_pidinfo( processes[i].kp_proc.p_pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo)); if (sizeof(taskinfo) != rc) { DEBUGMSGTL(("swrun:load:arch", " proc_pidinfo returned %d\n", rc)); } else { uint64_t task_mem = taskinfo.ptinfo.pti_resident_size / 1024; union { u_quad_t uq; /* u_int64_t */ UnsignedWide uw; /* struct u_int32_t hi/lo */ } at, ns; at.uq = taskinfo.ptinfo.pti_total_user + taskinfo.ptinfo.pti_total_system; ns = at; ns.uq = ns.uq / 10000000LL; /* nano to deci */ if (task_mem > INT32_MAX) { DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "mem overflow\n")); task_mem = INT32_MAX; } if (ns.uq > INT32_MAX) { DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "time overflow\n")); ns.uq = INT32_MAX; } entry->hrSWRunPerfMem = task_mem; entry->hrSWRunPerfCPU = ns.uq; } } free(processes); DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n", (int)CONTAINER_SIZE(container))); return 0; }
/* * check_process_vnodes * check [process] current working directory * check [process] root directory * * in : pid * out : -1 if error * 0 if no match * 1 if match */ static int check_process_vnodes(fdOpenInfoRef info, int pid) { int buf_used; int status; struct proc_vnodepathinfo vpi; buf_used = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)); if (buf_used <= 0) { if (errno == ESRCH) { // if the process is gone return 0; } return -1; } else if (buf_used < sizeof(vpi)) { // if we didn't get enough information return -1; } // processing current working directory status = check_file(info, &vpi.pvi_cdir.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } // processing root directory status = check_file(info, &vpi.pvi_rdir.vip_vi.vi_stat); if (status != 0) { // if error or match return status; } return 0; }