static RList *r_debug_native_pids (int pid) { RList *list = r_list_new (); if (!list) return NULL; #if __WINDOWS__ && !__CYGWIN__ return w32_pids (pid, list); #elif __APPLE__ if (pid) { RDebugPid *p = xnu_get_pid (pid); if (p) r_list_append (list, p); } else { int i; for (i = 1; i < MAXPID; i++) { RDebugPid *p = xnu_get_pid (i); if (p) r_list_append (list, p); } } #elif __linux__ int i; char *ptr, buf[1024]; list->free = (RListFree)&r_debug_pid_free; if (pid) { DIR *dh; struct dirent *de; /* add the requested pid. should we do this? we don't even know if it's valid still.. */ r_list_append (list, r_debug_pid_new ("(current)", pid, 's', 0)); /* list parents */ dh = opendir ("/proc"); if (!dh) { r_sys_perror ("opendir /proc"); r_list_free (list); return NULL; } while ((de = readdir (dh))) { /* for each existing pid file... */ i = atoi (de->d_name); if (i <= 0) { continue; } /* try to read the status */ buf[0] = 0; if (procfs_pid_slurp (i, "status", buf, sizeof (buf)) == -1) { continue; } buf[sizeof (buf) - 1] = 0; /* look for the parent process id */ ptr = strstr (buf, "PPid:"); if (ptr) { int ppid = atoi (ptr + 6); /* if this is the requested process... */ if (i == pid) { //eprintf ("PPid: %d\n", ppid); /* append it to the list with parent */ r_list_append (list, r_debug_pid_new ( "(ppid)", ppid, 's', 0)); } /* ignore it if it is not one of our children */ if (ppid != pid) { continue; } /* it's a child of the requested pid, read it's command line and add it */ if (procfs_pid_slurp (ppid, "cmdline", buf, sizeof(buf)) == -1) { continue; } r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } closedir (dh); } else { /* try to bruteforce the processes * XXX(jjd): wouldn't listing the processes like before work better? */ for (i = 2; i < MAXPID; i++) { /* try to send signal 0, if it fails it must not be valid */ if (r_sandbox_kill (i, 0) == -1) continue; if (procfs_pid_slurp (i, "cmdline", buf, sizeof(buf)) == -1) continue; r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } #else /* rest is BSD */ #ifdef __NetBSD__ # define KVM_OPEN_FLAG KVM_NO_FILES # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getproc2 (kd, opt, arg, sizeof(struct kinfo_proc2), cntptr) # define KP_COMM(x) (x)->p_comm # define KP_PID(x) (x)->p_pid # define KP_PPID(x) (x)->p_ppid # define KINFO_PROC kinfo_proc2 #elif defined(__OpenBSD__) # define KVM_OPEN_FLAG KVM_NO_FILES # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getprocs (kd, opt, arg, sizeof(struct kinfo_proc), cntptr) # define KP_COMM(x) (x)->p_comm # define KP_PID(x) (x)->p_pid # define KP_PPID(x) (x)->p_ppid # define KINFO_PROC kinfo_proc #else # define KVM_OPEN_FLAG O_RDONLY # define KVM_GETPROCS(kd, opt, arg, cntptr) \ kvm_getprocs (kd, opt, arg, cntptr) # define KP_COMM(x) (x)->ki_comm # define KP_PID(x) (x)->ki_pid # define KP_PPID(x) (x)->ki_ppid # define KINFO_PROC kinfo_proc #endif char errbuf[_POSIX2_LINE_MAX]; struct KINFO_PROC* kp; int cnt = 0; kvm_t* kd = kvm_openfiles (NULL, NULL, NULL, KVM_OPEN_FLAG, errbuf); if (!kd) { eprintf ("kvm_openfiles says %s\n", errbuf); return NULL; } if (pid) { kp = KVM_GETPROCS (kd, KERN_PROC_PID, pid, &cnt); if (cnt == 1) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp), pid, 's', 0); if (p) r_list_append (list, p); /* we got our process, now fetch the parent process */ kp = KVM_GETPROCS (kd, KERN_PROC_PID, KP_PPID(kp), &cnt); if (cnt == 1) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp), KP_PID(kp), 's', 0); if (p) r_list_append (list, p); } } } else { kp = KVM_GETPROCS (kd, KERN_PROC_UID, geteuid(), &cnt); int i; for (i = 0; i < cnt; i++) { RDebugPid *p = r_debug_pid_new (KP_COMM(kp + i), KP_PID(kp + i), 's', 0); if (p) r_list_append (list, p); } } kvm_close(kd); #endif return list; }
static RList *r_debug_native_pids (int pid) { RList *list = r_list_new (); if (!list) return NULL; #if __WINDOWS__ && !__CYGWIN__ return w32_pids (pid, list); #elif __APPLE__ if (pid) { RDebugPid *p = xnu_get_pid (pid); if (p) r_list_append (list, p); } else { int i; for (i = 1; i < MAXPID; i++) { RDebugPid *p = xnu_get_pid (i); if (p) r_list_append (list, p); } } #else int i; char *ptr, buf[1024]; list->free = (RListFree)&r_debug_pid_free; if (pid) { DIR *dh; struct dirent *de; /* add the requested pid. should we do this? we don't even know if it's valid still.. */ r_list_append (list, r_debug_pid_new ("(current)", pid, 's', 0)); /* list parents */ dh = opendir ("/proc"); if (dh == NULL) { r_sys_perror ("opendir /proc"); r_list_free (list); return NULL; } while ((de = readdir (dh))) { /* for each existing pid file... */ i = atoi (de->d_name); if (i <= 0) { continue; } /* try to read the status */ buf[0] = 0; if (procfs_pid_slurp (i, "status", buf, sizeof (buf)) == -1) { continue; } buf[sizeof (buf) - 1] = 0; /* look for the parent process id */ ptr = strstr (buf, "PPid:"); if (ptr) { int ppid = atoi (ptr + 6); /* if this is the requested process... */ if (i == pid) { //eprintf ("PPid: %d\n", ppid); /* append it to the list with parent */ r_list_append (list, r_debug_pid_new ( "(ppid)", ppid, 's', 0)); } /* ignore it if it is not one of our children */ if (ppid != pid) { continue; } /* it's a child of the requested pid, read it's command line and add it */ if (procfs_pid_slurp (ppid, "cmdline", buf, sizeof(buf)) == -1) { continue; } r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } closedir (dh); } else { /* try to bruteforce the processes * XXX(jjd): wouldn't listing the processes like before work better? */ for (i = 2; i < MAXPID; i++) { /* try to send signal 0, if it fails it must not be valid */ if (r_sandbox_kill (i, 0) == -1) continue; if (procfs_pid_slurp (i, "cmdline", buf, sizeof(buf)) == -1) continue; r_list_append (list, r_debug_pid_new (buf, i, 's', 0)); } } #endif return list; }