Code:
#!/usr/bin/ksh
#
# COPYRIGHT (c) 2003 - SIMERIAN
#
# e: info@simerian.com
# w: www.simerian.com
#
# DISCLAIMER
# The author of this product does not accept any responsibility for
# loss or damages resulting from the use of said product and makes no
# warranty or representation, either express or implied, including but
# not limited to, any implied warranty of merchantability or fitness for a
# particular purpose. This product is provided "AS IS", and you, its user,
# assume all risks when using it.
#
# DISTRIBUTION
# You may freely redistribute this product subject to the following conditions:
# 1) that the whole product is redistributed, AND,
# 2) that the product or any of its components are NOT altered, AND,
# 3) that no charge be made for any redistribution (ex. consumables & handling).
#---v----1----v----2----v----3----v----4----v----5----v----6----v----7----v----
#--------------------------------------------------------------------------
ps_Tree () {
awk '
BEGIN {
ROOT="......"
INDENT_SPC=" " # 20 spaces for embedding depth **
INDENT_BIT="00000000000000000000" # 20 spaces for embedding depth
c_addr =01 ; clnColIDX_Key[c_addr] ="ADDR"
c_cls =02 ; clnColIDX_Key[c_cls] ="CLS"
c_cmd =03 ; clnColIDX_Key[c_cmd] ="CMD"
c_comd =04 ; clnColIDX_Key[c_comd] ="COMD"
c_command =05 ; clnColIDX_Key[c_command] ="COMMAND"
c_c =06 ; clnColIDX_Key[c_c] ="C"
c_elapsed =07 ; clnColIDX_Key[c_elapsed] ="ELAPSED"
c_f =08 ; clnColIDX_Key[c_f] ="F"
c_gid =09 ; clnColIDX_Key[c_gid] ="GID"
c_group =10 ; clnColIDX_Key[c_group] ="GROUP"
c_cpu =11 ; clnColIDX_Key[c_cpu] ="%CPU"
c_ni =12 ; clnColIDX_Key[c_ni] ="NI"
c_pgid =13 ; clnColIDX_Key[c_pgid] ="PGID"
c_pid =14 ; clnColIDX_Key[c_pid] ="PID"
c_ppid =15 ; clnColIDX_Key[c_ppid] ="PPID"
c_pri =16 ; clnColIDX_Key[c_pri] ="PRI"
c_prmid =17 ; clnColIDX_Key[c_prmid] ="PRMID"
c_prmgrp =18 ; clnColIDX_Key[c_prmgrp] ="PRMGRP"
c_rgid =19 ; clnColIDX_Key[c_rgid] ="RGID"
c_rgroup =20 ; clnColIDX_Key[c_rgroup] ="RGROUP"
c_ruid =21 ; clnColIDX_Key[c_ruid] ="RUID"
c_ruser =22 ; clnColIDX_Key[c_ruser] ="RUSER"
c_sid =23 ; clnColIDX_Key[c_sid] ="SID"
c_s =24 ; clnColIDX_Key[c_s] ="S"
c_stime =25 ; clnColIDX_Key[c_stime] ="STIME"
c_sz =26 ; clnColIDX_Key[c_sz] ="SZ"
c_time =27 ; clnColIDX_Key[c_time] ="TIME"
c_tt =28 ; clnColIDX_Key[c_tty] ="TT"
c_tty =29 ; clnColIDX_Key[c_tty] ="TTY"
c_uid =30 ; clnColIDX_Key[c_uid] ="UID"
c_user =31 ; clnColIDX_Key[c_user] ="USER"
c_vsz =32 ; clnColIDX_Key[c_vsz] ="VSZ"
c_wchan =33 ; clnColIDX_Key[c_wchan] ="WCHAN"
for (KeyIDX in clnColIDX_Key) {
NameIDX=clnColIDX_Key[KeyIDX]
clnColIDX_Name[NameIDX]=KeyIDX
}
c_Width=1
clnColObj[c_addr,c_Width] ="#|%8s"
clnColObj[c_cls,c_Width] ="#|%s"
clnColObj[c_cmd,c_Width] ="e|%s"
clnColObj[c_comd,c_Width] ="e|%s"
clnColObj[c_command,c_Width] ="e|%s"
clnColObj[c_c,c_Width] ="#|%s"
clnColObj[c_elapsed,c_Width] ="#|%s"
clnColObj[c_f,c_Width] ="#|%4s"
clnColObj[c_gid,c_Width] ="#|%s"
clnColObj[c_group,c_Width] ="#|%s"
clnColObj[c_cpu,c_Width] ="#|%s"
clnColObj[c_ni,c_Width] ="#|%2s"
clnColObj[c_pgid,c_Width] ="#|%s"
clnColObj[c_pid,c_Width] ="#|%5s"
clnColObj[c_ppid,c_Width] ="#|%5s"
clnColObj[c_pri,c_Width] ="#|%3s"
clnColObj[c_prmid,c_Width] ="#|%s"
clnColObj[c_prmgrp,c_Width] ="#|%s"
clnColObj[c_rgid,c_Width] ="#|%s"
clnColObj[c_rgroup,c_Width] ="#|%s"
clnColObj[c_ruid,c_Width] ="#|%s"
clnColObj[c_ruser,c_Width] ="#|%s"
clnColObj[c_sid,c_Width] ="#|%s"
clnColObj[c_s,c_Width] ="#|%1s"
clnColObj[c_stime,c_Width] ="8|%8s"
clnColObj[c_sz,c_Width] ="#|%5s"
clnColObj[c_time,c_Width] ="#|%7s"
clnColObj[c_tt,c_Width] ="#|%s"
clnColObj[c_tty,c_Width] ="#|%-8s"
clnColObj[c_uid,c_Width] ="#|%8s"
clnColObj[c_user,c_Width] ="#|%s"
clnColObj[c_vsz,c_Width] ="#|%s"
clnColObj[c_wchan,c_Width] ="#|%16s"
fDepth=0
}
function SortPIDAscending (p_IDX_Sort,p_SortMax) {
fComplete=0
while (fComplete == 0) {
fSwapped=0
for (SortNo=1; SortNo < p_SortMax; SortNo++) {
if (p_IDX_Sort[SortNo] > p_IDX_Sort[(SortNo+1)]) {
fSwapped=1
TMP=p_IDX_Sort[SortNo]
p_IDX_Sort[SortNo]=p_IDX_Sort[(SortNo+1)]
p_IDX_Sort[(SortNo+1)]=TMP
}
}
if (fSwapped == 0) fComplete=1
}
}
function TraceTree (p_ChildKey,p_SRCMax,p_IDX_SRC,p_IDX_TGT,p_SRCNo) {
SRCNo=1
Prefix=substr(INDENT_SPC,1,((EmbeddingDepth+0)*2))
while (SRCNo <= p_SRCMax) {
if (p_IDX_SRC[SRCNo] != "") {
if ((EmbeddingDepth+0) == 0) {
p_ChildKey=substr(p_IDX_SRC[SRCNo],1,6)
}
ParentKey=substr(p_IDX_SRC[SRCNo],1,6)
if (ParentKey == p_ChildKey) {
++TGTNo
p_IDX_TGT[TGTNo]=p_IDX_SRC[SRCNo]
p_IDX_SRC[SRCNo]=""
ChildKey=substr(p_IDX_TGT[TGTNo],7,6)
PIDVal=ChildKey+0
LineNo=IDX_pid[PIDVal]
IDX_stdin[LineNo,fDepth]=EmbeddingDepth+0
EmbeddingDepth++
SRCNo=TraceTree(ChildKey,p_SRCMax,p_IDX_SRC,p_IDX_TGT,SRCNo)
EmbeddingDepth--
Prefix=substr(INDENT_SPC,1,((EmbeddingDepth+0)*2))
}
}
SRCNo++
}
return p_SRCNo
}
NR == 1 {
sub("^[ ]*","",$0)
sub("[ ]*$","",$0)
gsub("[ ]+"," ",$0)
FldMax=split($0,cln," ")
fIndent=FldMax+1
for (FldNo=1; FldNo <= FldMax; FldNo++) {
for (NameIDX in clnColIDX_Name) {
if (cln[FldNo] == NameIDX) {
KeyIDX=clnColIDX_Name[NameIDX]
clnColObj[KeyIDX,c_Posn]=FldNo
clnFldObj[FldNo]=KeyIDX
}
}
}
fPID=0
fPPID=0
for (FldNo=1; FldNo <= FldMax; FldNo++) {
KeyIDX=clnFldObj[FldNo]
ColName=clnColIDX_Key[KeyIDX]
if (ColName == clnColIDX_Key[c_pid]) fPID=FldNo
if (ColName == clnColIDX_Key[c_ppid]) fPPID=FldNo
if (ColName == clnColIDX_Key[c_cmd]) fCMD=FldNo
if (ColName == clnColIDX_Key[c_comd]) fCMD=FldNo
if (ColName == clnColIDX_Key[c_command]) fCMD=FldNo
}
}
NR > 1 {
ChrPosn=1
for (FldNo=1; FldNo <= FldMax; FldNo++) {
KeyIDX=clnFldObj[FldNo]
ColWidth=clnColObj[KeyIDX,c_Width]
split(ColWidth,clnWidth,"|")
ColSize=clnWidth[1]
ColFormat=clnWidth[2]
FldData=""
if (ColSize == "#") {
SubString=substr($0,ChrPosn)
match(SubString,"^[ ]*[[:graph:]]+[ ]+")
FldData=substr(SubString,1,RLENGTH)
ColSize=RLENGTH
} else {
if (ColSize == "e") {
FldData=substr($0,ChrPosn)
ColSize=length($0)-ChrPosn
} else {
FldData=substr($0,ChrPosn,ColSize)
}
}
sub("^[ ]*","",FldData)
sub("[ ]*$","",FldData)
ChrPosn+=ColSize
IDX_stdin[NR-1,FldNo]=FldData
}
if (fPID) {
PIDVal=IDX_stdin[NR-1,fPID]
IDX_pid[PIDVal]=NR-1
SortKey=sprintf("%06d",PIDVal)
if (fPPID) {
PPIDVal=IDX_stdin[NR-1,fPPID]
IDX_ppid[PPIDVal]=NR-1
SortKey=sprintf("%06d%s",PPIDVal,SortKey)
}
IDX_SORT[NR-1]=SortKey
}
}
END {
LineMax=NR-1
OverflowMax=LineMax
if (fPID && fPPID) {
for (PPIDVal in IDX_ppid) {
if (IDX_pid[PPIDVal] == "") {
OverflowMax++
for (FldNo=1; FldNo <= FldMax; FldNo++) {
IDX_stdin[OverflowMax,FldNo]="-"
}
IDX_stdin[OverflowMax,fPID]=PPIDVal
IDX_stdin[OverflowMax,fPPID]="?"
IDX_stdin[OverflowMax,fCMD]="[parent]"
IDX_pid[PPIDVal]=OverflowMax
SortKey=sprintf("%6.6s%06d",ROOT,PPIDVal)
IDX_SORT[OverflowMax]=SortKey
}
}
}
if (fPID) SortPIDAscending(IDX_SORT,OverflowMax)
if (fPID) {
if (fPPID) {
TraceTree("",OverflowMax,IDX_SORT,IDX_TREE,1)
for (LineNo=1; LineNo <= OverflowMax; LineNo++) {
PIDVal=substr(IDX_TREE[LineNo],7,6)+0
stdinNo=IDX_pid[PIDVal]
for (FldNo=0; FldNo <= FldMax; FldNo++) {
IDX_stdout[LineNo,FldNo]=IDX_stdin[stdinNo,FldNo]
}
}
} else {
for (LineNo=1; LineNo <= OverflowMax; LineNo++) {
PIDVal=IDX_SORT[LineNo]+0
stdinNo=IDX_pid[PIDVal]
for (FldNo=1; FldNo <= FldMax; FldNo++) {
IDX_stdout[LineNo,FldNo]=IDX_stdin[stdinNo,FldNo]
}
}
}
} else {
for (LineNo=1; LineNo <= OverflowMax; LineNo++) {
for (FldNo=1; FldNo <= FldMax; FldNo++) {
IDX_stdout[LineNo,FldNo]=IDX_stdin[LineNo,FldNo]
}
}
}
DepthPrev=0
for (LineNo=OverflowMax; LineNo >= 1; LineNo--) {
DepthVal=IDX_stdout[LineNo,fDepth]
if (DepthVal > 0) {
if (DepthVal < DepthPrev) {
Prefix=substr(INDENT_BIT,1,DepthVal-1)
Suffix=substr(INDENT_BIT,DepthVal+1)
gsub("1","0",Suffix)
INDENT_BIT=sprintf("%s1%s",Prefix,Suffix)
} else {
if (DepthVal > DepthPrev) {
Prefix=substr(INDENT_BIT,1,DepthVal-1)
Suffix=substr(INDENT_BIT,DepthVal+1)
INDENT_BIT=sprintf("%s1%s",Prefix,Suffix)
}
}
} else {
gsub("1","0",INDENT_BIT)
}
DepthPrev=DepthVal
IDX_stdout[LineNo,fIndent]=sprintf("%s",INDENT_BIT)
}
for (FldNo=1; FldNo <= FldMax; FldNo++) {
KeyIDX=clnFldObj[FldNo]
ColWidth=clnColObj[KeyIDX,c_Width]
split(ColWidth,clnWidth,"|")
ColSize=clnWidth[1]
ColFormat=clnWidth[2]
printf ColFormat,clnColIDX_Key[KeyIDX]
printf " "
}
printf "\n"
for (LineNo=1; LineNo <= OverflowMax; LineNo++) {
INDENT_BIT=IDX_stdout[LineNo,fIndent]
sub("^0*$","",INDENT_BIT)
sub("1[0]*$","|_",INDENT_BIT)
gsub("1","| ",INDENT_BIT) # Replace with Pipe & 1 space
gsub("0"," ",INDENT_BIT) # Replace with 2 spaces
IDX_stdout[LineNo,fIndent]=sprintf("%s",INDENT_BIT)
for (FldNo=1; FldNo <= FldMax; FldNo++) {
if (FldNo == fCMD) {
printf "%s",IDX_stdout[LineNo,fIndent]
}
KeyIDX=clnFldObj[FldNo]
ColWidth=clnColObj[KeyIDX,c_Width]
split(ColWidth,clnWidth,"|")
ColSize=clnWidth[1]
ColFormat=clnWidth[2]
printf ColFormat,IDX_stdout[LineNo,FldNo]
printf " "
}
printf "\n"
}
}
' <&0
}
#--------------------------------------------------------------------------
ps ${*} | ps_Tree