--- /dev/null
+#! /bin/sh
+
+usage() {
+ echo "EXAMPLE (whole tree) : $0 | neato -T png > ps.png && open ps.png"
+ echo "EXAMPLE (user clusters): $0 | sdp -T png > ps.png && open ps.png"
+}
+
+
+compile() {
+ awk -v kernel="$(uname -v)" -v whoami="$(whoami)" \
+ '
+ BEGIN {
+ p2cmd[0] = "swapper/sched"
+ color_base = 20
+ color_incr = 30
+ color_hi = sprintf("grey%d", (color_base + (color_incr * 0)))
+ color_mid = sprintf("grey%d", (color_base + (color_incr * 1)))
+ color_low = sprintf("grey%d", (color_base + (color_incr * 2)))
+ }
+
+ NR > 1 {
+ p2pp[$1]=$2;
+ p2user_id[$1]=$3
+ p2user_name[$1]=$4
+ p2cmd[$1]=$5
+ user_names[$4]=1
+ }
+
+ END {
+ print "strict digraph G {";
+
+ print "start=0;";
+ print "colorscheme=brewer;";
+ print "fontsize=8;";
+ print "fontname=Helvetica;";
+ print "label=\"" kernel "\";";
+
+ printf(\
+ "edge [ fontsize=8 \
+ , fontname=Helvetica \
+ , len=2.0 \
+ , color=%s \
+ ];",
+ color_low\
+ )
+
+ print "node [ fontsize=8 \
+ , fontname=Helvetica \
+ , shape=ellipse \
+ ]; \
+ ";
+
+ ##### Vertices (clustered by user)
+ for (user in user_names) {
+ printf "subgraph \"cluster_%s\" {\n", user
+ printf "label=\"%s\"\n", user
+ for (p in p2pp) {
+ if (p2user_name[p] == user) {
+ color = p2user_name[p] == whoami ? color_hi : color_low
+ fontcolor = p2user_name[p] == whoami ? color_hi : color_mid
+ printf(\
+ "\"%d\"\
+ [ fontsize=8 \
+ , fontname=Helvetica \
+ , shape=ellipse \
+ , label=\"%s\n%d\" \
+ , color=\"%s\" \
+ , fontcolor=\"%s\" \
+ ];",
+ p,
+ p2cmd[p],
+ p,
+ color,
+ fontcolor\
+ )
+ }
+ }
+ print "}"
+ }
+
+ ##### Vertices (without a user)
+ for (p in p2cmd) {
+ if (!p2user_name[p]) {
+ printf(\
+ "\"%d\"\
+ [ fontsize=8 \
+ , fontname=Helvetica \
+ , shape=ellipse \
+ , label=\"%s\n%d\" \
+ , color=\"%s\" \
+ , fontcolor=\"%s\" \
+ ];",
+ p,
+ p2cmd[p],
+ p,
+ color_low,
+ color_mid\
+ )
+ }
+ }
+
+ ##### Edges (across clusters)
+ for (p in p2pp) {
+ printf "\"%d\" -> \"%d\";\n", p2pp[p], p, p
+ }
+
+ print "}";
+ }
+ '
+}
+
+
+procs() {
+ if [ "$(uname)" = 'Linux' ]; then
+ ps -eo pid,ppid,euid,euser,comm
+ else
+ ps -eco pid,ppid,euid,euser,comm
+ fi
+}
+
+
+main() {
+ case "$1" in
+ '--help') usage
+ ;;
+ *) procs | grep "$1" | compile
+ ;;
+ esac
+}
+
+
+main "$1"