URI: 
       ptree - plstree - ps and ls displayed as a tree
  HTML git clone git://bitreich.org/plstree git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/plstree
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
       ptree (3515B)
       ---
            1 #!/usr/bin/awk -f
            2 
            3 # pstree implementation in awk
            4 
            5 # Use ps(1) to generate a list of pid, ppid and other properties with
            6 # the command name, displayed as a tree built from the pid-ppid pairs:
            7 #
            8 #        USER     TT        NI   PID STAT COMMAND
            9 #        root     ?          0     1 Ss   runit
           10 #        josuah   ?          0 22437 S    ├─ startx
           11 #        josuah   ?          0 22451 S    │  └─ xinit
           12 #        root     tty7       0 22452 Rsl+ │     ├─ Xorg
           13 #        josuah   ?          0 22457 S    │     └─ dwm
           14 #        josuah   ?          0 24882 S    └─ runsvdir
           15 #        josuah   ?          0 24884 S       ├─ runsv
           16 #        josuah   ?          0 24887 S       │  ├─ svlogd
           17 #        josuah   ?          0 24890 S       │  └─ ratox
           18 #        josuah   ?          0 24885 S       └─ runsv
           19 #        josuah   ?          0 24405 S          ├─ tor
           20 #        josuah   ?          0 24889 S          └─ svlogd
           21 
           22 BEGIN {
           23         LINE = "│  ";
           24         NODE = "├─ ";
           25         TAIL = "└─ ";
           26         VOID = "   ";
           27 
           28         list(entries);
           29         NUM = 1; fill(entries, 1, 0);
           30         tree(entries, NUM);
           31 
           32         for (i = 1; i < NUM; i++) {
           33                 printf("%s", entries[i":info"]);
           34                 for (j = 1; entries[i":"j] != ""; j++)
           35                         printf("%s", entries[i":"j]);
           36                 printf("%-" 30 - j * 3 "s", entries[i":comm"]);
           37                 print(entries[i":args"]);
           38         }
           39 }
           40 
           41 # Build a relational database in <entries> from the output of ps: The
           42 # parent pid (ppid) -> pid pairs are used to accumulate a list of child
           43 # pid (serialized into a csv: ",234,532,454") later used for building
           44 # the tree.
           45 #
           46 # For each pid, "info" and "comm" are saved as well.
           47 
           48 function list(entries)
           49 {
           50         opt = "-o ppid,user,vsz,pid,stat,comm,args"
           51         cmd = "exec ps -ax " opt " 2>/dev/null";
           52         if (!(cmd | getline)) {
           53                 cmd = "exec ps " opt
           54                 cmd | getline;
           55         }
           56         sub(" *[^ ]+", "");
           57         print $0;
           58 
           59         for (num = 0; cmd | getline; num++) {
           60                 ppid = $1; pid = $4;
           61                 entries[ppid"cpid"] = entries[ppid"cpid"] "," pid;
           62                 sub(" *[^ ]+", "");
           63                 sub(" *[^ ]+ + *[^ ]+ + *[^ ]+ + *[^ ]+ +", "&\t");
           64                 sub("[^\t]+        [^ ]+ +", "&\t");
           65                 split($0, info, "\t");
           66                 sub(" *$" , "", info[2]);
           67                 entries[pid"info"] = info[1];
           68                 entries[pid"comm"] = info[2];
           69                 entries[pid"args"] = info[3];
           70         }
           71         close(cmd);
           72 
           73         return num - 1;
           74 }
           75 
           76 # Using the informations from the child pid in entries, build the absolute
           77 # path from PID 1 to each pid:
           78 #
           79 #        [ 1:[ 1:"1" ],
           80 #          2:[ 1:"1", 2:"456" ],
           81 #          3:[ 1:"1", 2:"456", 3:"1623" ],
           82 #          4:[ 1:"1", 2:"456", 3:"1721" ] ]
           83 #
           84 # With also ":info" and ":comm" for every row.
           85 #
           86 # Only the leaves are present, the intermediates components are LINE or
           87 # NODE if just before a leave
           88 #
           89 #        [ 1:[ 1:LINE, 2:LINE, 3:LINE, 4:LINE, 5:NODE, 6:"filename" ] ]
           90 
           91 function fill(entries, pid, lvl)
           92 {
           93         for (j = 0; j < lvl; j++)
           94                 entries[NUM":"j] = LINE;
           95         entries[NUM":"lvl] = NODE;
           96         entries[NUM":comm"] = entries[pid"comm"];
           97         entries[NUM":args"] = entries[pid"args"];
           98         entries[NUM":info"] = entries[pid"info"];
           99         NUM++;
          100         while (sub("[^,]*,", "", entries[pid"cpid"])) {
          101                 cpid = entries[pid"cpid"];
          102                 sub(",.*", "", cpid);
          103                 fill(entries, cpid, lvl + 1);
          104         }
          105 }
          106 
          107 # Transform entries into a tree by replacing some LINE by VOID when needed.
          108 # The tree is walked from the bottom to the top, and column by column
          109 # toward the right until an empty column is met.
          110 
          111 function tree(entries, num)
          112 {
          113         for (j = 0; !stop; j++) {
          114                 stop = tail = 1;
          115                 for (i = num; i > 0; i--) {
          116                         if (entries[i":"j] == LINE && tail) {
          117                                 entries[i":"j] = VOID;
          118                                 stop = 0;
          119                         } else if (entries[i":"j] == NODE && tail) {
          120                                 entries[i":"j] = TAIL;
          121                                 tail = stop = 0;
          122                         } else if (!entries[i":"j]) {
          123                                 tail = 1;
          124                         }
          125                 }
          126         }
          127 }