1#!/usr/bin/perl
2# sort_res.perl5 - Script to group & sort lsof output by resource
3#
4# Copyright (c) 2004, 2005 - Fabian Frederick <fabian.frederick@gmx.fr>
5#
6# This program/include file is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License as published
8# by the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program/include file is distributed in the hope that it will be
12# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program (in the main directory of the Linux-NTFS
18# distribution in the file COPYING); if not, write to the Free Software
19# Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20#
21# Note : 
22#	-This script uses lsof released by Victor A. Abell
23#	-lsof path recovery comes from standard perl scripts in there.
24#
25# Usage :
26#	perl sort_res.perl5 -> display used resources + size
27#	or perl sort_res.perl5 <program name>
28#
29# 12/2005 (FabF) 
30#	-size reset in loop (script was broken in 4.76)
31#	-isexec looking in .. (like other scripts)
32#	-display for one or all processes
33#	-removing unuseful line number arg.
34#	-display global size
35
36require 'getopts.pl';
37my @args = @_;
38
39# Set path to lsof.
40if (($LSOF = &isexec("../lsof")) eq "") {    # Some distros use lsof
41						    # out of $PATH
42    if (($LSOF = &isexec("lsof")) eq "") {	    # Then try . and $PATH
43	if (($LSOF = &isexec("../lsof")) eq "") {    # Then try ..
44	    print "can't execute $LSOF\n"; exit 1
45	}
46    }
47}
48
49if ($ARGV[0] ne ""){
50    $cmd="$LSOF -nPl -Fcns -c".$ARGV[0]."|";
51}else{
52    $cmd="$LSOF -nPl -Fcns|";	
53}
54
55#Parse lsof output to gather command, resource name, pid and size
56#Some extradata stand to keep script genericity 
57$i=0;
58if (open(FILE, $cmd)){
59    while (defined ($line=<FILE>)){
60	$cline=$line;
61	$cline =~ s"^(.)"";
62	$cline =~ s/^\s+|\s+$//g;
63	if($line=~m/^p/){
64	    $pid=$cline;
65	}else{
66	    if($line=~/^s/){
67		$size = $cline;
68	    }else{
69		if($line=~/^c/){
70		    $command = $cline;
71		}else{
72		    if($line=~/^n/){
73			$name = $cline;
74			$data{$i} = { command => $command, name => $name,
75				      pid => $pid , size => $size};
76			$size=0;
77			$i = $i+1;
78		    }
79		}
80	    }
81	}
82    }
83}
84
85#Resource name sorting
86sub byresname { $data{$a}{name} cmp $data{$b}{name}}
87@ks=sort byresname (keys %data);
88
89#Resource grouping
90$i=0;
91$cname="a";
92foreach $k (@ks){
93    if ($data{$k}{name} ne $cname){
94	$dgroup{$i} = { name => $data{$k}{name}, size => $data{$k}{size}};
95	$cname = $data{$k}{name};
96	$i++;
97    }	
98}
99
100#Size sort on resource hash
101sub bysize { $dgroup{$a}{size} <=> $dgroup{$b}{size} }
102@ks=sort bysize (keys %dgroup);
103$gsize=0;
104printf("  -- KB --  -- Resource --\n", );
105foreach $k (@ks){
106	printf("%10d  %s\n", $dgroup{$k}{size}/1024, $dgroup{$k}{name});
107	$gsize+=$dgroup{$k}{size};
108}
109
110printf("Total KB : %10d\n", $gsize/1024);
111## isexec($path) -- is $path executable
112#
113# $path   = absolute or relative path to file to test for executabiity.
114#	    Paths that begin with neither '/' nor '.' that arent't found as
115#	    simple references are also tested with the path prefixes of the
116#	    PATH environment variable.  
117
118sub
119isexec {
120    my ($path) = @_;
121    my ($i, @P, $PATH);
122
123    $path =~ s/^\s+|\s+$//g;
124    if ($path eq "") { return(""); }
125    if (($path =~ m#^[\/\.]#)) {
126	if (-x $path) { return($path); }
127	return("");
128    }
129    $PATH = $ENV{PATH};
130    @P = split(":", $PATH);
131    for ($i = 0; $i <= $#P; $i++) {
132	if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
133    }
134    return("");
135}
136