1#!/usr/local/bin/perl
2#
3# count_pf.perl5 -- run lsof in repeat mode and count processes and
4#		    files
5
6sub interrupt { print "\n"; exit 0; }
7
8$RPT = 15;				# lsof repeat time
9
10# Set path to lsof.
11
12if (($LSOF = &isexec("../lsof")) eq "") {	# Try .. first
13    if (($LSOF = &isexec("lsof")) eq "") {	# Then try . and $PATH
14	print "can't execute $LSOF\n"; exit 1
15    }
16}
17
18# Read lsof -nPF0 output repeatedly from a pipe.
19
20$| = 1;					# unbuffer output
21$SIG{'INT'} = 'interrupt';		# catch interrupt
22$proc = $files = $tcp = $udp = 0;
23$progress="/";
24open(P, "$LSOF -nPF0 -r $RPT|") || die "can't open pipe to $LSOF\n";
25
26LSOF_LINE:
27
28while (<P>) {
29    chop;
30    if (/^m/) {
31
32    # A marker line signals the end of an lsof repetition.
33
34	printf "%s  Processes: %5d,  Files: %6d,  TCP: %6d, UDP: %6d\r",
35	    $progress, $proc, $files, $tcp, $udp;
36	$proc = $files = $tcp = $udp = 0;
37	if ($progress eq "/") { $progress = "\\"; } else { $progress = "/"; }
38	next LSOF_LINE;
39    }
40    if (/^p/) {
41
42    # Count process.
43
44	$proc++;
45	next LSOF_LINE;
46    }
47    if (/^f/) {
48
49    # Count files.
50
51	$files++;
52	@F = split("\0", $_, 999);
53	foreach $i (0 .. ($#F - 1)) {
54
55	# Search for protocol field.
56
57	    if ($F[$i] =~ /^P(.*)/) {
58
59	    # Count instances of TCP and UDP protocols.
60
61		if ($1 eq "TCP") { $tcp++; }
62		elsif ($1 eq "UDP") { $udp++; }
63		next LSOF_LINE;
64	    }
65	}
66    }
67}
68
69
70## isexec($path) -- is $path executable
71#
72# $path   = absolute or relative path to file to test for executabiity.
73#	    Paths that begin with neither '/' nor '.' that arent't found as
74#	    simple references are also tested with the path prefixes of the
75#	    PATH environment variable.  
76
77sub
78isexec {
79    my ($path) = @_;
80    my ($i, @P, $PATH);
81
82    $path =~ s/^\s+|\s+$//g;
83    if ($path eq "") { return(""); }
84    if (($path =~ m#^[\/\.]#)) {
85	if (-x $path) { return($path); }
86	return("");
87    }
88    $PATH = $ENV{PATH};
89    @P = split(":", $PATH);
90    for ($i = 0; $i <= $#P; $i++) {
91	if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
92    }
93    return("");
94}
95