Index: bin/ps/ps.c =================================================================== --- bin/ps/ps.c +++ bin/ps/ps.c @@ -170,7 +170,7 @@ "%cpu,%mem,command"; static char Zfmt[] = "label"; -#define PS_ARGS "AaCcde" OPT_LAZY_f "G:gHhjJ:LlM:mN:O:o:p:rSTt:U:uvwXxZ" +#define PS_ARGS "AaCcD::de" OPT_LAZY_f "G:gHhjJ:LlM:mN:O:o:p:rSTt:U:uvwXxZ" int main(int argc, char *argv[]) @@ -182,12 +182,13 @@ KINFO_STR *ks; struct varent *vent; struct winsize ws = { .ws_row = 0 }; - const char *nlistf, *memf, *str; + const char *nlistf, *memf, *str, *traverse_opts = ""; char *cols; int all, ch, elem, flag, _fmt, i, lineno, linelen, left; int descendancy, nentries, nkept, nselectors; int prtheader, wflag, what, xkeep, xkeep_implied; int fwidthmin, fwidthmax; + struct { int traversed; int initial; } pid_count; char errbuf[_POSIX2_LINE_MAX]; char fmtbuf[_POSIX2_LINE_MAX]; @@ -264,6 +265,10 @@ case 'c': cflag = 1; break; + case 'D': + descendancy = 1; + traverse_opts = optarg != NULL ? optarg : "$"; + break; case 'd': descendancy = 1; break; @@ -504,7 +509,7 @@ what = KERN_PROC_PGRP | showthreads; flag = *pgrplist.l.pids; nselectors = 0; - } else if (pidlist.count == 1) { + } else if (pidlist.count == 1 && traverse_opts[0] == 0) { what = KERN_PROC_PID | showthreads; flag = *pidlist.l.pids; nselectors = 0; @@ -539,6 +544,33 @@ if ((kp == NULL && errno != ESRCH) || (kp != NULL && nentries < 0)) xo_errx(1, "%s", kvm_geterr(kd)); nkept = 0; + pid_count.initial = pidlist.count; + if (strchr(traverse_opts, '$') != NULL) + for (elem = 0; elem < pidlist.count; elem++) + for (i = 0; i < nentries; i++) { + if (kp[i].ki_ppid == kp[i].ki_pid) + continue; + if (kp[i].ki_ppid == pidlist.l.pids[elem]) { + if (pidlist.count >= pidlist.maxcount) + expand_list(&pidlist); + pidlist.l.pids[pidlist.count++] = kp[i].ki_pid; + } + } + pid_count.traversed = pidlist.count; + if (strchr(traverse_opts, '^') != NULL) + for (elem = 0; elem < pidlist.count; elem++) { + if (elem >= pid_count.initial && elem < pid_count.traversed) + continue; + for (i = 0; i < nentries; i++) { + if (kp[i].ki_ppid == kp[i].ki_pid) + continue; + if (kp[i].ki_pid == pidlist.l.pids[elem]) { + if (pidlist.count >= pidlist.maxcount) + expand_list(&pidlist); + pidlist.l.pids[pidlist.count++] = kp[i].ki_ppid; + } + } + } if (nentries > 0) { if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) xo_errx(1, "malloc failed");