diff --git a/bin/ps/ps.c b/bin/ps/ps.c --- a/bin/ps/ps.c +++ b/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[]) @@ -188,8 +188,10 @@ 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]; + enum { NONE = 0, UP = 1, DOWN = 2, BOTH = 1 | 2 } directions = NONE; (void) setlocale(LC_ALL, ""); time(&now); /* Used by routines in print.c. */ @@ -264,6 +266,18 @@ case 'c': cflag = 1; break; + case 'D': { + size_t len = strlen(optarg); + + descendancy = 1; + if (len <= 2 && + strncasecmp(optarg, "up", len) == 0) + directions |= UP; + if (len <= 4 && + strncasecmp(optarg, "down", len) == 0) + directions |= DOWN; + break; + } case 'd': descendancy = 1; break; @@ -504,7 +518,7 @@ what = KERN_PROC_PGRP | showthreads; flag = *pgrplist.l.pids; nselectors = 0; - } else if (pidlist.count == 1) { + } else if (pidlist.count == 1 && directions == NONE) { what = KERN_PROC_PID | showthreads; flag = *pidlist.l.pids; nselectors = 0; @@ -539,6 +553,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 (directions & DOWN) + 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 (directions & UP) + 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");