summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPatrick McCarty <patrick.mccarty@linux.intel.com>2013-02-08 13:26:27 -0800
committerPatrick McCarty <patrick.mccarty@linux.intel.com>2013-02-08 13:26:27 -0800
commit9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7 (patch)
tree881eebfa461e4f8aa6b6f44b96ac0decd3bc887a /scripts
downloadlsof-9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7.tar.gz
lsof-9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7.tar.bz2
lsof-9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7.zip
Imported Upstream version 4.87upstream/4.87
Diffstat (limited to 'scripts')
-rw-r--r--scripts/00MANIFEST58
-rw-r--r--scripts/00README55
-rwxr-xr-xscripts/big_brother.perl5210
-rwxr-xr-xscripts/count_pf.perl68
-rwxr-xr-xscripts/count_pf.perl594
-rwxr-xr-xscripts/identd.perl5131
-rwxr-xr-xscripts/idrlogin.perl201
-rwxr-xr-xscripts/idrlogin.perl5197
-rwxr-xr-xscripts/list_NULf.perl5161
-rw-r--r--scripts/list_fields.awk198
-rwxr-xr-xscripts/list_fields.perl156
-rwxr-xr-xscripts/shared.perl5409
-rwxr-xr-xscripts/sort_res.perl5135
-rwxr-xr-xscripts/watch_a_file.perl94
-rwxr-xr-xscripts/xusers.awk137
15 files changed, 2304 insertions, 0 deletions
diff --git a/scripts/00MANIFEST b/scripts/00MANIFEST
new file mode 100644
index 0000000..79d6fb3
--- /dev/null
+++ b/scripts/00MANIFEST
@@ -0,0 +1,58 @@
+The scripts in this subdirectory give examples of using lsof's
+field output.
+
+big_brother.perl5 Perl 5 script, contributed by Lionel Cons
+ <Lionel.Cons@cern.ch>, that watches for new
+ network connections.
+
+count_pf.perl Perl 4 or 5 script that runs lsof in repeat
+ mode, gathering process, file, TCP, and UDP
+ counts
+
+count_pf.perl5 Perl 5 script that runs lsof in repeat mode,
+ gathering process, file, TCP, and UDP counts
+
+ This script uses NUL terminated lsof field
+ output.
+
+identd.perl5 Perl 5 script, contributed by Kapil Chowksey
+ <kchowksey@hss.hns.com> that implements an
+ identd server. (Thanks, Kapil!)
+
+idrlogin.perl Perl 4 script that identifies the shell and
+ network source address of users who have logged
+ on from remote locations via rlogin, ssh, or
+ telnet
+
+idrlogin.perl5 Perl 5 script that identifies the shell and
+ network source address of users who have logged
+ on from remote locations via rlogin, ssh, or
+ telnet
+
+list_NULf.perl5 Perl 5 script that prints lsof's NUL terminated
+ field output
+
+list_fields.awk AWK script that prints lsof's field output
+
+list_fields.perl Perl 4 or 5 script that prints lsof's field
+ output
+
+shared.perl5 Perl 5 script that uses +ffn output to produce
+ a list of file descriptors or files shared by
+ processes.
+
+sort_res.perl5 Perl 5 script, contributed by Fabian Frederick
+ <fabian.frederick@gmx.fr>, to display top resource
+ usage.
+
+watch_a_file.perl Perl 4 or 5 script that watches the use of a
+ named file
+
+xusers.awk an AWK (actually NAWK) script, written by
+ Dan A. Mercer <damercer@mmm.com> that, "Prints
+ list of users and applications signed on X
+ workstations." This script was developed
+ and is used with lsof on HP-UX systems.
+
+Vic Abell
+December 28, 1998
diff --git a/scripts/00README b/scripts/00README
new file mode 100644
index 0000000..3cfb9e6
--- /dev/null
+++ b/scripts/00README
@@ -0,0 +1,55 @@
+
+ Notes on Using the Scripts in This Subdirectory
+
+The scripts in this subdirectory are examples of post-processing
+lsof field output. Some are contributed by lsof users and are
+reproduced substantially as written by those users. Since the
+scripts are examples, they are not guaranteed to work on all UNIX
+dialects. Use them to learn about processing field output, don't
+expect them to be ready for production, and expect to be required
+to modify them to make them work.
+
+If you want to do field output post-processing in a C program, take
+a look at the test suite C library in ../tests/LTlib.c. You may
+be able to adapt it to your needs.
+
+The scripts are written in AWK, Perl 4 (4.036), and Perl 5 (5.001e
+through 5.006). AWK scripts have a suffix of ``.awk''; Perl 4
+(which will work under Perl 5) scripts have a ``.perl4'' suffix;
+and Perl 5 scripts, ``.perl''.
+
+Supply AWK scripts to your AWK interpreter with its -f option. Supply
+lsof field output via a pipe -- e.g.,
+
+ lsof -F | awk -f list_fields.awk
+
+The Perl scripts use the Unix command interpreter line feature to
+specify the location of Perl -- i.e., the first line begins with
+``#!'' and the path to the Perl interpreter follows. If your system
+supports the command interpreter feature, but your Perl interpreters
+have different paths to them, just change the interpreter lines in
+the scripts. These scripts assume:
+
+ Path to: Is:
+ ======= ==
+
+ Perl 4 /usr/local/bin/perl4
+
+ Perl 5 /usr/local/bin/perl
+
+If your system doesn't support the command interpreter feature,
+you'll have to supply the scripts to your Perl interpreter on its
+command line -- e.g.,
+
+ lsof -F | /<path_to_your_perl_4> list_fields.perl
+
+The Perl scripts attempt to establish a path to lsof, putting their
+result in the $LSOF variable. Assuming you'll run them from the
+scripts subdirectory, they look there first, then in the directories
+of the PATH environment variable. If that proves unsuitable, modify
+the &isexec() subroutine calls in the scripts to suit your lsof
+location.
+
+
+Vic Abell
+April 4, 2002
diff --git a/scripts/big_brother.perl5 b/scripts/big_brother.perl5
new file mode 100755
index 0000000..14c67a8
--- /dev/null
+++ b/scripts/big_brother.perl5
@@ -0,0 +1,210 @@
+#!/usr/local/bin/perl -w
+#+##############################################################################
+# #
+# File: big_brother.perl #
+# #
+# Description: check the network sockets with lsof to detect new connections #
+# #
+# Contributed by Lionel Cons <Lionel.Cons@cern.ch> #
+# #
+#-##############################################################################
+
+# @(#)big_brother 1.12 08/14/96 Written by Lionel.Cons@cern.ch
+
+# no waranty! use this at your own risks!
+
+#
+# init & setup
+#
+$verbose = 1;
+$lsof_opt = "-itcp -iudp -Di -FcLPn -r 5";
+$SIG{'HUP'} = \&hangup;
+chop($hostname = `/bin/hostname`);
+$fq_hostname = (gethostbyname($hostname))[0];
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+#
+# spy forever...
+#
+$| = 1;
+die "$LSOF is not executable\n" unless -x $LSOF;
+while (1) {
+ $lsof_pid = open(PIPE, "$LSOF $lsof_opt 2>&1 |")
+ || die "can't start $LSOF: $!\n";
+ print "# ", &timestamp, " $LSOF $lsof_opt, pid=$lsof_pid\n"
+ if $verbose;
+ print "#COMMAND PID USER P NAME\n";
+ $printed = $hanguped = $pid = $proto = 0;
+ while (<PIPE>) {
+ if (/^lsof: PID \d+, /) {
+ # fatal error message?
+ print "*** $_";
+ last;
+ } elsif (/^lsof: /) {
+ # warning
+ warn "* $_";
+ } elsif (/^p(\d+)$/) {
+ &flush;
+ $pid = $1;
+ $proto = 0;
+ } elsif (/^c(.*)$/) {
+ $command = $1;
+ } elsif (/^L(.*)$/) {
+ $user = $1;
+ } elsif (/^P(.*)$/) {
+ &flush;
+ $proto = $1;
+ } elsif (/^n(.*)$/) {
+ $name = $1;
+ # replace local hostname by 'localhost'
+ $name =~ s/\Q$fq_hostname\E/localhost/g;
+ $name =~ s/[0-9hms]+ ago//g;
+ } elsif (/^m$/) {
+ &flush;
+ &clean;
+ } else {
+ warn "* bad output ignored: $_";
+ }
+ }
+ kill('INT', $lsof_pid);
+ kill('KILL', $lsof_pid);
+ close(PIPE);
+}
+
+sub hangup {
+ $hanguped = 1;
+ $SIG{'HUP'} = \&hangup;
+}
+
+sub flush {
+ return unless $pid && $proto;
+ return if &skip;
+ $tag = sprintf("%-9s %5d %8s %1s %s", $command, $pid, $user,
+ substr($proto, 0, 1), $name);
+ unless (defined($seen{$tag})) {
+ print "+$tag\n";
+ $printed++;
+ }
+ $seen{$tag} = 1;
+}
+
+sub clean {
+ my(@to_delete, $tag);
+
+ if ($hanguped) {
+ $hanguped = 0;
+ @to_delete = keys(%seen);
+ print "# ", &timestamp, " hangup received, rescanning all connections\n"
+ if $verbose;
+ } else {
+ @to_delete = ();
+ foreach $tag (keys(%seen)) {
+ if ($seen{$tag} == 0) {
+ # not seen this time: delete it
+ push(@to_delete, $tag);
+ print "-$tag\n";
+ $printed++;
+ } else {
+ # seen this time: reset the flag
+ $seen{$tag} = 0;
+ }
+ }
+ }
+ grep(delete($seen{$_}), @to_delete);
+ if ($printed > 10) {
+ print "# ", &timestamp, "\n" if $verbose;
+ $printed = 0;
+ }
+}
+
+sub skip {
+ #
+ # put stuff here to ignore some connections, for instance:
+ #
+
+ # what we get when the socket gets created...
+ return(1) if $name eq '*:0';
+ return(1) if $name =~ /^localhost:(\d+)$/ && $1 > 1000;
+#
+# UDP & TCP stuff
+#
+ #
+ # ignore common daemons
+ #
+ if ($name =~ /^\*:/ && $user eq 'root' && $pid < 300) {
+ return(1) if $command =~ /^inetd(\.afs)?$/;
+ return(1) if $command =~ /^rpc\.(stat|lock)d$/;
+ return(1) if $command eq 'syslogd' && $name eq '*:syslog';
+ }
+ #
+ # forking beasts: portmap, ypbind, inetd
+ #
+ if ($command eq 'portmap' && $user eq 'daemon') {
+ return(1) if $name =~ /^\*:/;
+ } elsif ($command eq 'ypbind') {
+ return(1) if $name =~ /^\*:\d+$/;
+ }
+#
+# TCP-only stuff
+#
+ return(0) unless $proto eq 'TCP';
+ #
+ # outgoing commands: ftp, telnet, r*
+ #
+ if ($command eq 'ftp') {
+ return(1) if $name =~ /:ftp(-data)?$/;
+ } elsif ($command eq 'telnet') {
+ return(1) if $name =~ /:telnet$/;
+ } elsif ($command eq 'remsh') {
+ if ($name =~ /:(\d?\d\d\d)->.+:(\d?\d\d\d)$/) {
+ return(1) if $1 < 1024 && $1 > 990 && $2 < 1024 && $2 > 990;
+ } elsif ($name =~ /:(\d?\d\d\d)->.+:(shell|ta-rauth)$/) {
+ return(1) if $1 < 1024 && $1 > 990;
+ } elsif ($name =~ /^\*:(\d?\d\d\d)$/) {
+ return(1) if $1 < 1024 && $1 > 990;
+ }
+ }
+ return(0);
+}
+
+sub timestamp {
+ my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
+
+ ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+ sprintf("%d/%02d/%02d-%02d:%02d:%02d", $year + 1900, $mon+1, $mday,
+ $hour, $min, $sec);
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/count_pf.perl b/scripts/count_pf.perl
new file mode 100755
index 0000000..f063697
--- /dev/null
+++ b/scripts/count_pf.perl
@@ -0,0 +1,68 @@
+#!/usr/local/bin/perl
+#
+# count_pf.perl-- run lsof in repeat mode and count processes and
+# files
+
+sub interrupt { print "\n"; exit 0; }
+
+$RPT = 15; # lsof repeat time
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Read lsof -nPF output repeatedly from a pipe.
+
+$| = 1; # unbuffer output
+$SIG{'INT'} = 'interrupt'; # catch interrupt
+$proc = $files = $proto{'TCP'} = $proto{'UDP'} = 0;
+$progress="/"; # used to show "progress"
+open(P, "$LSOF -nPF -r $RPT|") || die "can't open pipe to $LSOF\n";
+
+while (<P>) {
+ chop;
+ if (/^m/) {
+
+ # A marker line signals the end of an lsof repetition.
+
+ printf "%s Processes: %5d, Files: %6d, TCP: %6d, UDP: %6d\r",
+ $progress, $proc, $files, $proto{'TCP'}, $proto{'UDP'};
+ $proc = $files = $proto{'TCP'} = $proto{'UDP'} = 0;
+ if ($progress eq "/") { $progress = "\\"; } else { $progress = "/"; }
+ next;
+ }
+ if (/^p/) { $proc++; next; } # Count processes.
+ if (/^f/) { $files++; next; } # Count files.
+ if (/^P(.*)/) { $proto{$1}++; next; } # Count protocols.
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/count_pf.perl5 b/scripts/count_pf.perl5
new file mode 100755
index 0000000..6b87f78
--- /dev/null
+++ b/scripts/count_pf.perl5
@@ -0,0 +1,94 @@
+#!/usr/local/bin/perl
+#
+# count_pf.perl5 -- run lsof in repeat mode and count processes and
+# files
+
+sub interrupt { print "\n"; exit 0; }
+
+$RPT = 15; # lsof repeat time
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Read lsof -nPF0 output repeatedly from a pipe.
+
+$| = 1; # unbuffer output
+$SIG{'INT'} = 'interrupt'; # catch interrupt
+$proc = $files = $tcp = $udp = 0;
+$progress="/";
+open(P, "$LSOF -nPF0 -r $RPT|") || die "can't open pipe to $LSOF\n";
+
+LSOF_LINE:
+
+while (<P>) {
+ chop;
+ if (/^m/) {
+
+ # A marker line signals the end of an lsof repetition.
+
+ printf "%s Processes: %5d, Files: %6d, TCP: %6d, UDP: %6d\r",
+ $progress, $proc, $files, $tcp, $udp;
+ $proc = $files = $tcp = $udp = 0;
+ if ($progress eq "/") { $progress = "\\"; } else { $progress = "/"; }
+ next LSOF_LINE;
+ }
+ if (/^p/) {
+
+ # Count process.
+
+ $proc++;
+ next LSOF_LINE;
+ }
+ if (/^f/) {
+
+ # Count files.
+
+ $files++;
+ @F = split("\0", $_, 999);
+ foreach $i (0 .. ($#F - 1)) {
+
+ # Search for protocol field.
+
+ if ($F[$i] =~ /^P(.*)/) {
+
+ # Count instances of TCP and UDP protocols.
+
+ if ($1 eq "TCP") { $tcp++; }
+ elsif ($1 eq "UDP") { $udp++; }
+ next LSOF_LINE;
+ }
+ }
+ }
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/identd.perl5 b/scripts/identd.perl5
new file mode 100755
index 0000000..32626d8
--- /dev/null
+++ b/scripts/identd.perl5
@@ -0,0 +1,131 @@
+#!/usr/local/bin/perl
+###################################################################
+# identd.perl5 : An implementation of RFC 1413 Ident Server
+# using Vic Abell's lsof.
+#
+# - Started from inetd with 'nowait' option. This entry in
+# /etc/inetd.conf will suffice :
+#
+# ident stream tcp nowait root /usr/local/bin/identd.perl5 -t200
+#
+# - Multiple instances of the server are not a performance penalty
+# since they shall use lsof's cacheing mechanism. (compare with
+# Peter Eriksson's pidentd)
+# - assumes 'lsof' binary in /usr/local/sbin
+# - Command line arguments :
+# -t TIMEOUT Number of seconds to wait for a query before aborting.
+# Default is 120.
+#
+# Kapil Chowksey <kchowksey@hss.hns.com>
+###################################################################
+
+use Socket;
+require 'getopts.pl';
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# redirect lsof's warnings/errors to /dev/null
+close(STDERR);
+open(STDERR, ">/dev/null");
+
+$Timeout = "120";
+
+&Getopts('t:');
+if ($opt_t) {
+ $Timeout = $opt_t;
+}
+
+($port, $iaddr) = sockaddr_in(getpeername(STDIN));
+$peer_addr = inet_ntoa($iaddr);
+
+# read ident-query from socket (STDIN) with a timeout.
+$timeout = int($Timeout);
+eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ alarm $timeout;
+ $query = <STDIN>;
+ alarm 0;
+};
+die if $@ && $@ ne "alarm\n";
+if ($@) {
+ # timed out
+ exit;
+}
+
+# remove all white-spaces from query
+$query =~ s/\s//g;
+
+$serv_port = "";
+$cli_port = "";
+($serv_port,$cli_port) = split(/,/,$query);
+
+if ($serv_port =~ /^[0-9]+$/) {
+ if (int($serv_port) < 1 || int($serv_port) > 65535) {
+ print $query." : ERROR : INVALID-PORT"."\n";
+ exit;
+ }
+} else {
+ print $query." : ERROR : INVALID-PORT"."\n";
+ exit;
+}
+
+if ($cli_port =~ /^[0-9]+$/) {
+ if (int($cli_port) < 1 || int($cli_port) > 65535) {
+ print $query." : ERROR : INVALID-PORT"."\n";
+ exit;
+ }
+} else {
+ print $query." : ERROR : INVALID-PORT"."\n";
+ exit;
+}
+
+open(LSOFP,"$LSOF -nPDi -T -FLn -iTCP@".$peer_addr.":".$cli_port."|");
+
+$user = "UNKNOWN";
+while ($a_line = <LSOFP>) {
+ # extract user name.
+ if ($a_line =~ /^L.*/) {
+ ($user) = ($a_line =~ /^L(.*)/);
+ }
+
+ # make sure local port matches.
+ if ($a_line =~ /^n.*:\Q$serv_port->/) {
+ print $serv_port.", ".$cli_port." : USERID : UNIX :".$user."\n";
+ exit;
+ }
+}
+
+print $serv_port.", ".$cli_port." : ERROR : NO-USER"."\n";
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/idrlogin.perl b/scripts/idrlogin.perl
new file mode 100755
index 0000000..d244dc7
--- /dev/null
+++ b/scripts/idrlogin.perl
@@ -0,0 +1,201 @@
+#!/usr/local/bin/perl
+#
+# $Id: idrlogin.perl,v 1.5 2001/11/18 12:20:46 abe Exp $
+#
+# idrlogin.perl -- sample Perl script to identify the network source of a
+# network (remote) login via rlogind, sshd, or telnetd
+
+
+# IMPORTANT DEFINITIONS
+# =====================
+#
+# 1. Set the interpreter line of this script to the local path of the
+# Perl executable.
+
+
+#
+# Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Initialize variables.
+
+$dev = $name = $proto = ""; # fd variables
+$fdst = 0; # fd state
+$pidst = 0; # process state
+$cmd = $login = $pid = $ppid = ""; # process var.
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Open a pipe from lsof.
+
+open(P, "$LSOF -R -FcDfLpPRn|") || die "Can't pipe from $LSOF\n";
+
+# Process the ``lsof -FcDfLpPRn'' output a line at a time
+
+while (<P>) {
+ chop;
+ if (/^p(.*)/) {
+
+# A process set begins with a PID field whose ID character is `p'.
+
+ $tpid = $1;
+ if ($pidst && $fdst) { &save_proc }
+ $pidst = 1;
+ $pid = $tpid;
+ $cmd = $login = $ppid = "";
+ $fdst = 0;
+ $dev = $name = $proto = "";
+ next;
+ }
+
+# Save process-related values.
+
+ if (/^c(.*)/) { $cmd = $1; next; }
+ if (/^L(.*)/) { $login = $1; next; }
+ if (/^R(.*)/) { $ppid = $1; next; }
+
+# A file set begins with a file descriptor field.
+
+ if (/^f/) {
+ if ($pidst && $fdst) { &save_proc }
+ $fdst = 0;
+ $dev = $name = $proto = "";
+ next;
+ }
+
+# Accumulate file information.
+
+ if (/^D(.*)/) { $dev = $1; next; }
+ if (/^P(.*)/) { $proto = $1; next; }
+ if (/^n(.*)/) { $name = $1; $fdst = 1; next; }
+}
+
+# Flush any stored file or process output.
+
+if ($pidst && $fdst) { &save_proc }
+
+# List the shell processes that have rlogind/sshd//telnetd parents.
+
+$hdr = 0;
+foreach $pid (sort keys(%shcmd)) {
+ $p = $pid;
+ if (!defined($raddr{$pid})) {
+ for ($ff = 0; !$ff && defined($Ppid{$p}); ) {
+ $p = $Ppid{$p};
+ if ($p < 2 || defined($raddr{$p})) { $ff = 1; }
+ }
+ } else { $ff = 2; }
+ if ($ff && defined($raddr{$p})) {
+ if (!$hdr) {
+ printf "%-8.8s %-8.8s %6s %-10.10s %6s %-10.10s %s\n",
+ "Login", "Shell", "PID", "Via", "PID", "TTY", "From";
+ $hdr = 1;
+ }
+ printf "%-8.8s %-8.8s %6d %-10.10s %6s %-10.10s %s\n",
+ $shlogin{$pid}, $shcmd{$pid}, $pid,
+ ($ff == 2) ? "(direct)" : $rcmd{$p},
+ ($ff == 2) ? "" : $p,
+ ($shtty{$pid} eq "") ? "(unknown)" : $shtty{$pid},
+ $raddr{$p};
+ }
+}
+exit(0);
+
+
+# save_proc -- save process information
+# Values are stored inelegantly in global variables.
+
+sub save_proc {
+ if ($cmd eq ""
+ || $login eq ""
+ || $ppid eq ""
+ || $pid eq ""
+ || $name eq ""
+ ) { return; }
+ if (!defined($Ppid{$pid})) { $Ppid{$pid} = $ppid; }
+ if ($proto eq "TCP"
+ && (($cmd =~ /rlogind/) || ($cmd =~ /sshd/) || ($cmd =~ /telnetd/))) {
+ if (defined($raddr{$pid})) { return; }
+ if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) {
+ $raddr{$pid} = $1;
+ $rcmd{$pid} = $cmd;
+ return;
+ }
+ }
+ if (($cmd =~ /.*sh$/)) {
+ if (defined($shcmd{$pid})) { return; }
+ if ($proto eq "TCP") {
+ if (defined($raddr{$pid})) { return; }
+ if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) {
+ $raddr{$pid} = $1;
+ $shcmd{$pid} = $cmd;
+ $shlogin{$pid} = $login;
+ }
+ }
+ if (($name =~ m#/dev.*ty.*#)) {
+ ($tty) = ($name =~ m#/dev.*/(.*)#);
+ } elsif (($name =~ m#/dev/(pts/\d+)#)) {
+ $tty = $1;
+ } elsif (($name =~ m#/dev.*pts.*#)) {
+ $d = oct($dev);
+ $tty = sprintf("pts/%d", $d & 0xffff);
+ } else { return; }
+ } else { return; }
+ $shcmd{$pid} = $cmd;
+ $shtty{$pid} = $tty;
+ $shlogin{$pid} = $login;
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/idrlogin.perl5 b/scripts/idrlogin.perl5
new file mode 100755
index 0000000..5e7e4bf
--- /dev/null
+++ b/scripts/idrlogin.perl5
@@ -0,0 +1,197 @@
+#!/usr/local/bin/perl
+#
+# $Id: idrlogin.perl5,v 1.5 2001/11/18 12:20:46 abe Exp $
+#
+# idrlogin.perl5 -- sample Perl 5 script to identify the network source of a
+# network (remote) login via rlogind, sshd, or telnetd
+
+
+# IMPORTANT DEFINITIONS
+# =====================
+#
+# 1. Set the interpreter line of this script to the local path of the
+# Perl 5 executable.
+
+
+# Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Initialize variables.
+
+$dev = $faddr = $tty = ""; # fd variables
+$pidst = 0; # process state
+$cmd = $login = $pgrp = $pid = $ppid = ""; # process var.
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Open a pipe from lsof
+
+if (! -x "$LSOF") { die "Can't execute $LSOF\n"; }
+open (P, "$LSOF -R -FcDfLpPRn0|") || die "Can't pipe from $LSOF\n";
+
+# Process the lsof output a line at a time
+
+while (<P>) {
+ chop;
+ @F = split('\0', $_, 999);
+ if ($F[0] =~ /^p/) {
+
+# A process set begins with a PID field whose ID character is `p'.
+
+ if ($pidst) { &save_proc }
+ foreach $i (0 .. ($#F - 1)) {
+
+ PROC: {
+ if ($F[$i] =~ /^c(.*)/) { $cmd = $1; last PROC }
+ if ($F[$i] =~ /^p(.*)/) { $pid = $1; last PROC }
+ if ($F[$i] =~ /^R(.*)/) { $ppid = $1; last PROC }
+ if ($F[$i] =~ /^L(.*)/) { $login = $1; last PROC }
+ }
+ }
+ $pidst = 1;
+ next;
+ }
+
+# A file descriptor set begins with a file descriptor field whose ID
+# character is `f'.
+
+ if ($F[0] =~ /^f/) {
+ if ($faddr ne "") { next; }
+ $proto = $name = "";
+ foreach $i (0 .. ($#F - 1)) {
+
+ FD: {
+ if ($F[$i] =~ /^P(.*)/) { $proto = $1; last FD; }
+ if ($F[$i] =~ /^n(.*)/) { $name = $1; last FD; }
+ if ($F[$i] =~ /^D(.*)/) { $dev = $1; last FD; }
+ }
+ }
+ if ($proto eq "TCP"
+ && $faddr eq ""
+ && (($cmd =~ /rlogind/) || ($cmd =~ /sshd/) || ($cmd =~ /telnetd/))) {
+ if (($name =~ /[^:]*:[^-]*->([^:]*):.*/)) {
+ $faddr = $1;
+ }
+ } elsif ($tty eq "" && ($cmd =~ /.*sh$/)) {
+ if (($name =~ m#/dev.*ty.*#)) {
+ ($tty) = ($name =~ m#/dev.*/(.*)#);
+ } elsif (($name =~ m#/dev/(pts/\d+)#)) {
+ $tty = $1;
+ } elsif (($name =~ m#/dev.*pts.*#)) {
+ $d = oct($dev);
+ $tty = sprintf("pts/%d", $d & 0xffff);
+ }
+ }
+ next;
+ }
+}
+
+# Flush any stored file or process output.
+
+if ($pidst) { &save_proc }
+
+# List the shell processes that have rlogind/sshd/telnetd parents.
+
+$hdr = 0;
+foreach $pid (sort keys(%shcmd)) {
+ $p = $pid;
+ if (!defined($raddr{$pid})) {
+ for ($ff = 0; !$ff && defined($Ppid{$p}); ) {
+ $p = $Ppid{$p};
+ if ($p < 2 || defined($raddr{$p})) { $ff = 1; }
+ }
+ } else { $ff = 2; }
+ if ($ff && defined($raddr{$p})) {
+ if (!$hdr) {
+ printf "%-8.8s %-8.8s %6s %-10.10s %6s %-10.10s %s\n",
+ "Login", "Shell", "PID", "Via", "PID", "TTY", "From";
+ $hdr = 1;
+ }
+ printf "%-8.8s %-8.8s %6d %-10.10s %6s %-10.10s %s\n",
+ $shlogin{$pid}, $shcmd{$pid}, $pid,
+ ($ff == 2) ? "(direct)" : $rcmd{$p},
+ ($ff == 2) ? "" : $p,
+ ($shtty{$pid} eq "") ? "(unknown)" : $shtty{$pid},
+ $raddr{$p};
+ }
+}
+exit(0);
+
+
+# save_proc -- save process information
+# Values are stored inelegantly in global variables.
+
+sub save_proc {
+ if (!defined($Ppid{$pid})) { $Ppid{$pid} = $ppid; }
+ if ($faddr ne "") {
+ $raddr{$pid} = $faddr;
+ if (($cmd =~ /.*sh$/)) {
+ $shcmd{$pid} = $cmd;
+ $shlogin{$pid} = $login;
+ } else { $rcmd{$pid} = $cmd; }
+ }
+ if ($tty ne "") {
+ $shcmd{$pid} = $cmd;
+ $shtty{$pid} = $tty;
+ $shlogin{$pid} = $login;
+ }
+
+# Clear variables.
+
+ $cmd = $dev = $faddr = $pgrp = $pid = $ppid = $tty = "";
+ $pidst = 0;
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/list_NULf.perl5 b/scripts/list_NULf.perl5
new file mode 100755
index 0000000..a9cdbed
--- /dev/null
+++ b/scripts/list_NULf.perl5
@@ -0,0 +1,161 @@
+#!/usr/local/bin/perl
+#
+# $Id: list_NULf.perl5,v 1.5 2000/07/14 17:03:37 abe Exp $
+#
+# list_NULf.perl5 -- sample Perl 5 script to list lsof NUL-terminated
+# full field output (i.e., -F0 output)
+#
+# This script has been tested under perl version 5.001e.
+#
+# Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Initialize variables.
+
+$fhdr = 0; # fd hdr. flag
+$fdst = 0; # fd state
+$access = $devch = $devn = $fd = $inode = $lock = $name = ""; # | file descr.
+$offset = $proto = $size = $state = $stream = $type = ""; # | variables
+$pidst = 0; # process state
+$cmd = $login = $pgrp = $pid = $ppid = $uid = ""; # process var.
+
+# Process the ``lsof -F'' output a line at a time, gathering
+# the variables for a process together before printing them;
+# then gathering the variables for each file descriptor
+# together before printing them.
+
+while (<>) {
+ chop;
+ @F = split('\0', $_, 999);
+ if ($F[0] =~ /^p/) {
+
+# A process set begins with a PID field whose ID character is `p'.
+
+ if ($pidst) { &list_proc }
+ if ($fdst) { &list_fd; $fdst = 0; }
+ foreach $i (0 .. ($#F - 1)) {
+
+ PROC: {
+ if ($F[$i] =~ /^c(.*)/) { $cmd = $1; last PROC }
+ if ($F[$i] =~ /^g(.*)/) { $pgrp = $1; last PROC }
+ if ($F[$i] =~ /^p(.*)/) { $pid = $1; last PROC }
+ if ($F[$i] =~ /^u(.*)/) { $uid = $1; last PROC }
+ if ($F[$i] =~ /^L(.*)/) { $login = $1; last PROC }
+ if ($F[$i] =~ /^R(.*)/) { $ppid = $1; last PROC }
+ print "ERROR: unrecognized process field: \"$F[$i]\"\n";
+ }
+ }
+ $pidst = 1;
+ next;
+ }
+
+# A file descriptor set begins with a file descriptor field whose ID
+# character is `f'.
+
+ if ($F[0] =~ /^f/) {
+ if ($pidst) { &list_proc }
+ if ($fdst) { &list_fd }
+ foreach $i (0 .. ($#F - 1)) {
+
+ FD: {
+ if ($F[$i] =~ /^a(.*)/) { $access = $1; last FD; }
+ if ($F[$i] =~ /^C(.*)/) { last FD; }
+ if ($F[$i] =~ /^f(.*)/) { $fd = $1; last FD; }
+ if ($F[$i] =~ /^F(.*)/) { last FD; }
+ if ($F[$i] =~ /^d(.*)/) { $devch = $1; last FD; }
+ if ($F[$i] =~ /^D(.*)/) { $devn = $1; last FD; }
+ if ($F[$i] =~ /^G(.*)/) { last FD; }
+ if ($F[$i] =~ /^i(.*)/) { $inode = $1; last FD; }
+ if ($F[$i] =~ /^k(.*)/) { last FD; }
+ if ($F[$i] =~ /^l(.*)/) { $lock = $1; last FD; }
+ if ($F[$i] =~ /^N(.*)/) { last FD; }
+ if ($F[$i] =~ /^o(.*)/) { $offset = $1; last FD; }
+ if ($F[$i] =~ /^P(.*)/) { $proto = $1; last FD; }
+ if ($F[$i] =~ /^s(.*)/) { $size = $1; last FD; }
+ if ($F[$i] =~ /^S(.*)/) { $stream = $1; last FD; }
+ if ($F[$i] =~ /^t(.*)/) { $type = $1; last FD; }
+ if ($F[$i] =~ /^T(.*)/) {
+ if ($state eq "") { $state = "(" . $1; }
+ else { $state = $state . " " . $1; }
+ last FD;
+ }
+ if ($F[$i] =~ /^n(.*)/) { $name = $1; last FD; }
+ print "ERROR: unrecognized file set field: \"$F[$i]\"\n";
+ }
+ }
+ $fdst = 1;
+ next;
+ }
+ print "ERROR: unrecognized: \"$_\"\n";
+}
+
+# Flush any stored file or process output.
+
+if ($fdst) { &list_fd }
+if ($pidst) { &list_proc }
+exit(0);
+
+
+## list_fd -- list file descriptor information
+# Values are stored inelegantly in global variables.
+
+sub list_fd {
+ if ( ! $fhdr) {
+
+ # Print header once.
+
+ print " FD TYPE DEVICE SIZE/OFF INODE NAME\n";
+ $fhdr = 1;
+ }
+ printf " %4s%1.1s%1.1s %4.4s", $fd, $access, $lock, $type;
+ $tmp = $devn; if ($devch ne "") { $tmp = $devch }
+ printf " %10.10s", $tmp;
+ $tmp = $size; if ($offset ne "") { $tmp = $offset }
+ printf " %10.10s", $tmp;
+ $tmp = $inode; if ($proto ne "") { $tmp = $proto }
+ printf " %10.10s", $tmp;
+ $tmp = $stream; if ($name ne "") { $tmp = $name }
+ print " ", $tmp;
+ if ($state ne "") { printf " %s)\n", $state; } else { print "\n"; }
+
+# Clear variables.
+
+ $access = $devch = $devn = $fd = $inode = $lock = "";
+ $name = $offset = $proto = $size = $state = $stream = $type = "";
+}
+
+
+# list_proc -- list process information
+# Values are stored inelegantly in global variables.
+
+sub list_proc {
+ print "COMMAND PID PGRP PPID USER\n";
+ $tmp = $uid; if ($login ne "") {$tmp = $login }
+ printf "%-9.9s %6d %6d %6d %s\n", $cmd, $pid, $pgrp, $ppid, $tmp;
+
+# Clear variables.
+
+ $cmd = $login = $pgrp = $pid = $uid = "";
+ $fhdr = $pidst = 0;
+}
diff --git a/scripts/list_fields.awk b/scripts/list_fields.awk
new file mode 100644
index 0000000..d8fbbb4
--- /dev/null
+++ b/scripts/list_fields.awk
@@ -0,0 +1,198 @@
+# $Id: list_fields.awk,v 1.3 97/09/23 09:32:38 abe Exp $
+#
+# list_fields.awk -- sample awk script to list lsof full field output
+# (i.e., -F output without -0)
+#
+# NB: this is not particularly elegant awk; several sections were
+# replicated, perhaps unnecessarily, to produce a sample quickly
+# and simply.
+#
+#
+# Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Clear file and process status.
+
+BEGIN {
+ fhdr = fdst = pidst = 0;
+ access = dev = devch = fd = inode = lock = name = offset = "";
+ proto = size = state = stream = type = "";
+ cmd = login = pgrp = pid = ppid = uid = "";
+}
+
+# Start a new process.
+
+/^p/ {
+ val = substr($0, 2);
+ if (pidst) {
+
+ # Print a previously accumulated process set.
+
+ printf "COMMAND PID PGRP PPID USER\n";
+ printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid;
+ if (login != "") { printf " %s\n", login }
+ else { printf " %s\n", uid }
+ pidst = 0;
+ cmd = login = pgrp = pid = uid = "";
+ }
+ if (fdst) {
+
+ # Print a previously accumulated file set.
+
+ if (fhdr == 0) {
+ printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n";
+ }
+ printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type;
+ t = dev; if (devch != "") { t = devch }
+ printf(" %10.10s", t);
+ t = size; if (offset != "") { t = offset }
+ printf " %10.10s", t;
+ t = inode; if (proto != "") { t = proto }
+ printf " %10.10s", t;
+ t = stream; if (name != "") {t = name }
+ printf " %s", t;
+ if (state != "") { printf " %s)\n", state } else { printf "\n" }
+ access = dev = devch = fd = inode = lock = name = offset = "";
+ proto = size = state = stream = type = "";
+ fdst = fhdr = 0
+ }
+
+# Record a new process.
+
+ pidst = 1;
+ pid = val;
+}
+
+/^g|^c|^u|^L|^R/ {
+
+# Save process set information.
+
+ id = substr($0, 1, 1);
+ val = substr($0, 2);
+ if (id == "g") { pgrp = val; next } # PGRP
+ if (id == "c") { cmd = val; next } # command
+ if (id == "u") { uid = val; next } # UID
+ if (id == "L") { login = val; next } # login name
+ if (id == "R") { ppid = val; next } # PPID
+}
+
+/^f|^a|^l|^t|^d|^D|^s|^o|^i|^P|^S|^T|^n/ {
+
+# Save file set information.
+
+ id = substr($0, 1, 1);
+ val = substr($0, 2);
+ if (id == "f") {
+ if (pidst) {
+
+ # Print a previously accumulated process set.
+
+ printf "COMMAND PID PGRP PPID USER\n";
+ printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid;
+ if (login != "") { printf " %s\n", login }
+ else { printf " %s\n", uid }
+ pidst = 0;
+ cmd = login = pgrp = pid = uid = "";
+ }
+ if (fdst) {
+
+ # Print a previously accumulated file set.
+
+ if (fhdr == 0) {
+ printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n";
+ }
+ fhdr = 1;
+ printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type;
+ t = dev; if (devch != "") { t = devch }
+ printf(" %10.10s", t);
+ t = size; if (offset != "") { t = offset }
+ printf " %10.10s", t;
+ t = inode; if (proto != "") { t = proto }
+ printf " %10.10s", t;
+ t = stream; if (name != "") {t = name }
+ printf " %s", t;
+ if (state != "") { printf " %s)\n", state } else { printf "\n" }
+ access = dev = devch = fd = inode = lock = name = offset = "";
+ proto = size = state = stream = type = "";
+ }
+
+ # Start an new file set.
+
+ fd = val;
+ fdst = 1;
+ next;
+ }
+
+# Save file set information.
+
+ if (id == "a") { access = val; next } # access
+ if (id == "l") { lock = val; next } # lock
+ if (id == "t") { type = val; next } # type
+ if (id == "d") { devch = val; next } # device characters
+ if (id == "D") { dev = val; next } # device major/minor numbers
+ if (id == "s") { size = val; next } # size
+ if (id == "o") { offset = val; next } # offset
+ if (id == "i") { inode = val; next } # inode number
+ if (id == "P") { proto = val; next } # protocol
+ if (id == "S") { stream = val; next } # stream name
+ if (id == "T") { # TCP/TPI state
+ if (state == "") {
+ state = sprintf("(%s", val);
+ } else {
+ state = sprintf("%s %s", state, val);
+ }
+ next
+ }
+ if (id == "n") { name = val; next } # name, comment, etc.
+}
+
+END {
+ if (pidst) {
+
+ # Print last process set.
+
+ printf "COMMAND PID PGRP PPID USER\n";
+ printf "%-9.9s %6d %6d %6d", cmd, pid, pgrp, ppid;
+ if (login != "") { printf " %s\n", login }
+ else { printf " %s\n", uid }
+ }
+ if (fdst) {
+
+ # Print last file set.
+
+ if (fhdr == 0) {
+ printf " FD TYPE DEVICE SIZE/OFF INODE NAME\n";
+ }
+ printf " %4.4s%1.1s%1.1s %4.4s", fd, access, lock, type;
+ t = dev; if (devch != "") { t = devch }
+ printf(" %10.10s", t);
+ t = size; if (offset != "") { t = offset }
+ printf " %10.10s", t;
+ t = inode; if (proto != "") { t = proto }
+ printf " %10.10s", t;
+ t = stream; if (name != "") {t = name }
+ printf " %s", t;
+ if (state != "") { printf " %s)\n", state; } else { printf "\n"; }
+ }
+}
diff --git a/scripts/list_fields.perl b/scripts/list_fields.perl
new file mode 100755
index 0000000..41bd3e4
--- /dev/null
+++ b/scripts/list_fields.perl
@@ -0,0 +1,156 @@
+#!/usr/local/bin/perl4
+#
+# $Id: list_fields.perl,v 1.5 2000/07/14 17:03:37 abe Exp $
+#
+# list_fields.perl -- sample Perl script to list lsof full field output
+# (i.e., -F output without -0)
+#
+# This script has been tested under perl versions 4.036 and 5.001e.
+#
+# Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Initialize variables.
+
+$fhdr = 0; # fd hdr. flag
+$fdst = 0; # fd state
+$access = $devch = $devn = $fd = $inode = $lock = $name = ""; # | file descr.
+$offset = $proto = $size = $state = $stream = $type = ""; # | variables
+$pidst = 0; # process state
+$cmd = $login = $pgrp = $pid = $ppid = $uid = ""; # process var.
+
+# Process the ``lsof -F'' output a line at a time, gathering
+# the variables for a process together before printing them;
+# then gathering the variables for each file descriptor
+# together before printing them.
+
+while (<>) {
+ chop;
+ if (/^p(.*)/) {
+
+# A process set begins with a PID field whose ID character is `p'.
+
+ $tpid = $1;
+ if ($pidst) { &list_proc }
+ $pidst = 1;
+ $pid = $tpid;
+ if ($fdst) { &list_fd; $fdst = 0; }
+ next;
+ }
+
+# Save process-related values.
+
+ if (/^g(.*)/) { $pgrp = $1; next; }
+ if (/^c(.*)/) { $cmd = $1; next; }
+ if (/^u(.*)/) { $uid = $1; next; }
+ if (/^L(.*)/) { $login = $1; next; }
+ if (/^R(.*)/) { $ppid = $1; next; }
+
+# A file descriptor set begins with a file descriptor field whose ID
+# character is `f'.
+
+ if (/^f(.*)/) {
+ $tfd = $1;
+ if ($pidst) { &list_proc }
+ if ($fdst) { &list_fd }
+ $fd = $tfd;
+ $fdst = 1;
+ next;
+ }
+
+# Save file set information.
+
+ if (/^a(.*)/) { $access = $1; next; }
+ if (/^C(.*)/) { next; }
+ if (/^d(.*)/) { $devch = $1; next; }
+ if (/^D(.*)/) { $devn = $1; next; }
+ if (/^F(.*)/) { next; }
+ if (/^G(.*)/) { next; }
+ if (/^i(.*)/) { $inode = $1; next; }
+ if (/^k(.*)/) { next; }
+ if (/^l(.*)/) { $lock = $1; next; }
+ if (/^N(.*)/) { next; }
+ if (/^o(.*)/) { $offset = $1; next; }
+ if (/^P(.*)/) { $proto = $1; next; }
+ if (/^s(.*)/) { $size = $1; next; }
+ if (/^S(.*)/) { $stream = $1; next; }
+ if (/^t(.*)/) { $type = $1; next; }
+ if (/^T(.*)/) {
+ if ($state eq "") { $state = "(" . $1; }
+ else { $state = $state . " " . $1; }
+ next;
+ }
+ if (/^n(.*)/) { $name = $1; next; }
+ print "ERROR: unrecognized: \"$_\"\n";
+}
+
+# Flush any stored file or process output.
+
+if ($fdst) { &list_fd }
+if ($pidst) { &list_proc }
+exit(0);
+
+
+## list_fd -- list file descriptor information
+# Values are stored inelegantly in global variables.
+
+sub list_fd {
+ if ( ! $fhdr) {
+
+ # Print header once.
+
+ print " FD TYPE DEVICE SIZE/OFF INODE NAME\n";
+ $fhdr = 1;
+ }
+ printf " %4s%1.1s%1.1s %4.4s", $fd, $access, $lock, $type;
+ $tmp = $devn; if ($devch ne "") { $tmp = $devch }
+ printf " %10.10s", $tmp;
+ $tmp = $size; if ($offset ne "") { $tmp = $offset }
+ printf " %10.10s", $tmp;
+ $tmp = $inode; if ($proto ne "") { $tmp = $proto }
+ printf " %10.10s", $tmp;
+ $tmp = $stream; if ($name ne "") { $tmp = $name }
+ print " ", $tmp;
+ if ($state ne "") { printf " %s)\n", $state; } else { print "\n"; }
+
+# Clear variables.
+
+ $access = $devch = $devn = $fd = $inode = $lock = $name = "";
+ $offset = $proto = $size = $state = $stream = $type = "";
+}
+
+
+# list_proc -- list process information
+# Values are stored inelegantly in global variables.
+
+sub list_proc {
+ print "COMMAND PID PGRP PPID USER\n";
+ $tmp = $uid; if ($login ne "") {$tmp = $login }
+ printf "%-9.9s %6d %6d %6d %s\n", $cmd, $pid, $pgrp, $ppid, $tmp;
+
+# Clear variables.
+
+ $cmd = $login = $pgrp = $pid = $uid = "";
+ $fhdr = $pidst = 0;
+}
diff --git a/scripts/shared.perl5 b/scripts/shared.perl5
new file mode 100755
index 0000000..2721413
--- /dev/null
+++ b/scripts/shared.perl5
@@ -0,0 +1,409 @@
+#!/usr/local/bin/perl
+#
+# $Id: shared.perl5,v 1.4 2001/11/18 12:20:46 abe Exp $
+#
+# shared.perl5 -- sample Perl 5 script to list processes that share
+# file descriptors or files, using `lsof +ffn -F..."
+# output
+#
+# Usage: shared [fd|file]
+#
+# where: fd to list file descriptors (default)
+#
+# file to list files
+#
+# This script has been tested under perl version 5.001e.
+
+
+# IMPORTANT DEFINITIONS
+# =====================
+#
+# 1. Set the interpreter line of this script to the local path of the
+# Perl5 executable.
+
+
+# Copyright 1998 Purdue Research Foundation, West Lafayette, Indiana
+# 47907. All rights reserved.
+#
+# Written by Victor A. Abell <abe@purdue.edu>
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. Neither the authors nor Purdue University are responsible for any
+# consequences of the use of this software.
+#
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Credit to the authors and Purdue
+# University must appear in documentation and sources.
+#
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software.
+#
+# 4. This notice may not be removed or altered.
+
+# Initialize variables.
+
+$Access = $Devch = $Devn = $Fd = $Fsa = $Inode = $Lock = # file
+ $Na = $Name = ""; # | descriptor
+$Cmd = $Login = $Pgrp = $Pid = $Ppid = $Uid = ""; # process var.
+$Fdst = 0; # fd state
+$Hdr = 0; # header state
+$Offset = $Proto = $Size = $State = $Stream = $Type = ""; # | variables
+$Pidst = 0; # process state
+$Pn = "shared";
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Define print field constants.
+
+$CmdTtl = "CMD";
+$CmdW = length($CmdTtl);
+$DevTtl = "DEVICE";
+$DevW = length($DevTtl);
+$FdTtl = "FD";
+$FdW = length($FdTtl);
+$InoTtl = "NODE";
+$InoW = length($InoTtl);
+$KeyTtl = "FILEADDR";
+$KeyW = length($KeyTtl);
+$PidTtl = "PID";
+$PidW = length($PidTtl);
+$PpidTtl = "PPID";
+$PpidW = length(PpidTtl);
+
+# Process one (optional) argument.
+
+if ($#ARGV >= 0) {
+ $err = 0;
+ if ($#ARGV > 1) { $err = 1; }
+ elsif ($ARGV[0] eq "fd") {
+ $KeyTtl = "FILEADDR";
+ $Shfd = 1;
+ $Shfile = 0;
+ } elsif ($ARGV[0] eq "file") {
+ $KeyTtl = "NODEID";
+ $Shfd = 0;
+ $Shfile = 1;
+ } else { $err = 1; }
+ if ($err) { die "$Pn: usage [fd|file]\n"; }
+ shift;
+} else { $Shfd = 1; $Shfile = 0; }
+$KeyW = length($KeyTtl);
+
+# Open a pipe from lsof.
+
+if (!open(LSOF_PIPE, "$LSOF -R +ffn -F0pcRDfFinN |")) {
+ die "$Pn: can't open pipe to: $LSOF\n";
+}
+
+# Process the lsof output a line at a time, gathering the variables for
+# processes and files.
+
+while (<LSOF_PIPE>) {
+ chop;
+ @F = split('\0', $_, 999);
+ if ($F[0] =~ /^p/) {
+
+# A process set begins with a PID field whose ID character is `p'.
+
+ if ($Fdst) { &End_fd }
+ if ($Pidst) { &End_proc }
+ foreach $i (0 .. ($#F - 1)) {
+
+ PROC: {
+ if ($F[$i] =~ /^c(.*)/) { $Cmd = $1; last PROC }
+ if ($F[$i] =~ /^g(.*)/) { $Pgrp = $1; last PROC }
+ if ($F[$i] =~ /^p(.*)/) { $Pid = $1; last PROC }
+ if ($F[$i] =~ /^u(.*)/) { $Uid = $1; last PROC }
+ if ($F[$i] =~ /^L(.*)/) { $Login = $1; last PROC }
+ if ($F[$i] =~ /^R(.*)/) { $Ppid = $1; last PROC }
+ print "ERROR: unrecognized process field: \"$F[$i]\"\n";
+ }
+ }
+ $Pidst = 1;
+ next;
+ }
+
+# A file descriptor set begins with a file descriptor field whose ID
+# character is `f'.
+
+ if ($F[0] =~ /^f/) {
+ if ($Fdst) { &End_fd }
+ foreach $i (0 .. ($#F - 1)) {
+
+ FD: {
+ if ($F[$i] =~ /^a(.*)/) { $Access = $1; last FD; }
+ if ($F[$i] =~ /^f(.*)/) { $Fd = $1; last FD; }
+ if ($F[$i] =~ /^F(.*)/) { $Fsa = $1; last FD; }
+ if ($F[$i] =~ /^l(.*)/) { $Lock = $1; last FD; }
+ if ($F[$i] =~ /^t(.*)/) { $Type = $1; last FD; }
+ if ($F[$i] =~ /^d(.*)/) { $Devch = $1; last FD; }
+ if ($F[$i] =~ /^D(.*)/) { $Devn = $1; last FD; }
+ if ($F[$i] =~ /^s(.*)/) { $Size = $1; last FD; }
+ if ($F[$i] =~ /^o(.*)/) { $Offset = $1; last FD; }
+ if ($F[$i] =~ /^i(.*)/) { $Inode = $1; last FD; }
+ if ($F[$i] =~ /^P(.*)/) { $Proto = $1; last FD; }
+ if ($F[$i] =~ /^S(.*)/) { $Stream = $1; last FD; }
+ if ($F[$i] =~ /^T(.*)/) {
+ if ($State eq "") { $State = "(" . $1; }
+ else { $State = $State . " " . $1; }
+ last FD;
+ }
+ if ($F[$i] =~ /^n(.*)/) { $Name = $1; last FD; }
+ if ($F[$i] =~ /^N(.*)/) { $Na = $1; last FD; }
+ print "ERROR: unrecognized file set field: \"$F[$i]\"\n";
+ }
+ }
+ $Fdst = 1;
+ next;
+ }
+ print "ERROR: unrecognized: \"$_\"\n";
+}
+close(LSOF_PIPE);
+if ($Fdst) { &End_fd }
+if ($Pidst) { &End_proc }
+
+# List matching files or file descriptors.
+
+for ($pass = 0; $pass < 2; $pass++) {
+ foreach $key (sort keys(%Fds)) {
+ @Praw = split(' ', $Fds{$key}, 999);
+ if ($#Praw < 1) { next; }
+ if ($Shfd) { @P = sort Sort_by_FD_and_PID @Praw; }
+ else { @P = sort Sort_by_PID_and_FD @Praw; }
+
+ # Accumulate and print blocks of (key, PID, FD) triplets.
+
+ for ($i = 0; $i < $#P; $i++) {
+ if ($Shfile) {
+ for ($n = 0; $n <= $#P; $n++) {
+ ($pid, $fd) = split(",", $P[$n], 999);
+ $PrtPid[$n] = $pid;
+ $PrtFd[$n] = $fd;
+ }
+ $i = $n;
+ } else {
+ ($pid, $fd) = split(",", $P[$i], 999);
+ $PrtFd[0] = $fd;
+ $PrtPid[0] = $pid;
+ for ($n = 1; $i < $#P; $i++, $n++) {
+ ($nxtpid, $nxtfd) = split(",", $P[$i + 1], 999);
+ if ($fd ne $nxtfd) { last; }
+ $PrtFd[$n] = $nxtfd;
+ $PrtPid[$n] = $nxtpid;
+ }
+ }
+ if ($n > 1) { &Print_block($key, $n, $pass); }
+ }
+ }
+}
+exit(0);
+
+
+## End_fd() -- process end of file descriptor
+
+sub End_fd {
+
+ local ($key);
+
+ if ($Fdst && $Pidst && $Pid ne "") {
+ if ($Cmd ne "") { $Cmds{$Pid} = $Cmd; }
+ if ($Ppid ne "") { $Ppids{$Pid} = $Ppid; }
+ $key = $Shfd ? $Fsa : $Na;
+ if ($key ne "") {
+ if (!defined($Fds{$key})) { $Fds{$key} = "$Pid,$Fd"; }
+ else { $Fds{$key} .= " $Pid,$Fd"; }
+ if ($Name ne "" && !defined($Name{$key})) { $Name{$key} = $Name }
+ if ($Inode ne "" && !defined($Inodes{$key})) {
+ $Inodes{$key} = $Inode;
+ }
+ if ($Devn ne "" && !defined($Devns{$key})) {
+ $Devns{$key} = $Devn;
+ }
+ }
+ }
+
+# Clear variables.
+
+ $Access = $Devch = $Devn = $Fd = $Fsa = $Inode = $Lock = "";
+ $Na = $Name = $Offset = $Proto = $Size = $State = $Stream = $Type = "";
+ $Fdst = 0;
+}
+
+
+## End_proc() -- process end of process
+
+sub End_proc {
+
+# Clear variables.
+
+ $Cmd = $Login = $Pgrp = $Pid = $Ppid = $Uid = "";
+ $Fdst = $Pidst = 0;
+}
+
+
+## Print_block() -- print a block of entries
+#
+# entry:
+#
+# @_[0] = block's key
+# @_[1] = number of entries in the block
+# @_[2] = print pass status (1 == print)
+
+sub Print_block {
+
+ my ($key, $n, $pass) = @_;
+
+ local ($fd, $i, $pid, $t, $tW);
+
+ if ($pass) {
+ if (!$Hdr) {
+ printf "%${KeyW}.${KeyW}s", $KeyTtl;
+ printf " %${PidW}.${PidW}s", $PidTtl;
+ printf " %${PpidW}.${PpidW}s", $PpidTtl;
+ printf " %-${CmdW}.${CmdW}s", $CmdTtl;
+ printf " %${FdW}.${FdW}s", $FdTtl;
+ printf " %${DevW}.${DevW}s", $DevTtl;
+ printf " %${InoW}.${InoW}s", $InoTtl;
+ printf " NAME\n";
+ $Hdr = 1;
+ } else { print "\n"; }
+ }
+
+# Loop through block. During a non-print pass, caclulate maximum field widths.
+
+ for ($i = 0; $i < $n; $i++) {
+ $fd = $PrtFd[$i];
+ $pid = $PrtPid[$i];
+
+ # Process key.
+
+ if (!$pass) {
+ $tW = length(sprintf("%s", $key));
+ if ($tW > $KeyW) { $KeyW = $tW; }
+ } else { printf "%s", $key; }
+
+ # Process PID.
+
+ if (!$pass) {
+ $tW = length(sprintf(" %s", $pid));
+ if ($tW > $PidW) { $PidW = $tW; }
+ } else { printf " %${PidW}.${PidW}s", $pid; }
+
+ # Process parent PID.
+
+ $t = defined($Ppids{$pid}) ? $Ppids{$pid} : "";
+ if (!$pass) {
+ $tW = length(sprintf(" %s", $t));
+ if ($tW > $PpidW) { $PpidW = $tW; }
+ } else { printf " %${PpidW}.${PpidW}s", $t; }
+
+ # Process command name.
+
+ $t = defined($Cmds{$pid}) ? $Cmds{$pid} : "";
+ if (!$pass) {
+ $tW = length(sprintf(" %s", $t));
+ if ($tW > $CmdW) { $CmdW = $tW; }
+ } else { printf " %-${CmdW}.${CmdW}s", $t; }
+
+ # Process file descriptor.
+
+ if (!$pass) {
+ $tW = length(sprintf(" %s", $fd));
+ if ($tW > $FdW) { $FdW = $tW; }
+ } else { printf " %${FdW}.${FdW}s", $fd; }
+
+ # Process device number.
+
+ $t = defined($Devns{$key}) ? $Devns{$key} : "";
+ if (!$pass) {
+ $tW = length(sprintf(" %s", $t));
+ if ($tW > $DevW) { $DevW = $tW; }
+ } else { printf " %${DevW}.${DevW}s", $t; }
+
+ # Process node number.
+
+ $t = defined($Inodes{$key}) ? $Inodes{$key} : $t;
+ if (!$pass) {
+ $tW = length(sprintf (" %s", $t));
+ if ($tW > $InoW) { $InoW = $tW; }
+ } else { printf " %${InoW}.${InoW}s", $t; }
+
+ # Print name and line terminater, if this is a print pass.
+
+ if ($pass) {
+ if (defined($Name{$key})) { print " $Name{$key}\n"; }
+ else { print "\n"; }
+ }
+ }
+}
+
+
+## Sort_by_FD_and_PID() -- sort (PID,FD) doublets by FD first, then PID
+
+sub Sort_by_FD_and_PID {
+
+ local ($pida, $pidb, $fda, $fdj, $rv);
+
+ ($pida, $fda) = split(",", $a);
+ ($pidb, $fdb) = split(",", $b);
+ if ($fda < $fdb) { return(-1); }
+ if ($fda > $fdb) { return(1); }
+ if ($pida < $pidb) { return(-1); }
+ if ($pida > $pidb) { return(1); }
+ return(0);
+}
+
+
+## Sort_by_PID_and_FD() -- sort (PID,FD) doublets by PID first, then FD
+
+sub Sort_by_PID_and_FD {
+
+ local ($pida, $pidb, $fda, $fdj, $rv);
+
+ ($pida, $fda) = split(",", $a);
+ ($pidb, $fdb) = split(",", $b);
+ if ($pida < $pidb) { return(-1); }
+ if ($pida > $pidb) { return(1); }
+ if ($fda < $fdb) { return(-1); }
+ return(0);
+ if ($fda > $fdb) { return(1); }
+}
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/sort_res.perl5 b/scripts/sort_res.perl5
new file mode 100755
index 0000000..cf11950
--- /dev/null
+++ b/scripts/sort_res.perl5
@@ -0,0 +1,135 @@
+#!/usr/bin/perl
+# sort_res.perl5 - Script to group & sort lsof output by resource
+#
+# Copyright (c) 2004, 2005 - Fabian Frederick <fabian.frederick@gmx.fr>
+#
+# This program/include file is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program/include file is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program (in the main directory of the Linux-NTFS
+# distribution in the file COPYING); if not, write to the Free Software
+# Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Note :
+# -This script uses lsof released by Victor A. Abell
+# -lsof path recovery comes from standard perl scripts in there.
+#
+# Usage :
+# perl sort_res.perl5 -> display used resources + size
+# or perl sort_res.perl5 <program name>
+#
+# 12/2005 (FabF)
+# -size reset in loop (script was broken in 4.76)
+# -isexec looking in .. (like other scripts)
+# -display for one or all processes
+# -removing unuseful line number arg.
+# -display global size
+
+require 'getopts.pl';
+my @args = @_;
+
+# Set path to lsof.
+if (($LSOF = &isexec("../lsof")) eq "") { # Some distros use lsof
+ # out of $PATH
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ if (($LSOF = &isexec("../lsof")) eq "") { # Then try ..
+ print "can't execute $LSOF\n"; exit 1
+ }
+ }
+}
+
+if ($ARGV[0] ne ""){
+ $cmd="$LSOF -nPl -Fcns -c".$ARGV[0]."|";
+}else{
+ $cmd="$LSOF -nPl -Fcns|";
+}
+
+#Parse lsof output to gather command, resource name, pid and size
+#Some extradata stand to keep script genericity
+$i=0;
+if (open(FILE, $cmd)){
+ while (defined ($line=<FILE>)){
+ $cline=$line;
+ $cline =~ s"^(.)"";
+ $cline =~ s/^\s+|\s+$//g;
+ if($line=~m/^p/){
+ $pid=$cline;
+ }else{
+ if($line=~/^s/){
+ $size = $cline;
+ }else{
+ if($line=~/^c/){
+ $command = $cline;
+ }else{
+ if($line=~/^n/){
+ $name = $cline;
+ $data{$i} = { command => $command, name => $name,
+ pid => $pid , size => $size};
+ $size=0;
+ $i = $i+1;
+ }
+ }
+ }
+ }
+ }
+}
+
+#Resource name sorting
+sub byresname { $data{$a}{name} cmp $data{$b}{name}}
+@ks=sort byresname (keys %data);
+
+#Resource grouping
+$i=0;
+$cname="a";
+foreach $k (@ks){
+ if ($data{$k}{name} ne $cname){
+ $dgroup{$i} = { name => $data{$k}{name}, size => $data{$k}{size}};
+ $cname = $data{$k}{name};
+ $i++;
+ }
+}
+
+#Size sort on resource hash
+sub bysize { $dgroup{$a}{size} <=> $dgroup{$b}{size} }
+@ks=sort bysize (keys %dgroup);
+$gsize=0;
+printf(" -- KB -- -- Resource --\n", );
+foreach $k (@ks){
+ printf("%10d %s\n", $dgroup{$k}{size}/1024, $dgroup{$k}{name});
+ $gsize+=$dgroup{$k}{size};
+}
+
+printf("Total KB : %10d\n", $gsize/1024);
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/watch_a_file.perl b/scripts/watch_a_file.perl
new file mode 100755
index 0000000..c1cd782
--- /dev/null
+++ b/scripts/watch_a_file.perl
@@ -0,0 +1,94 @@
+#!/usr/local/bin/perl
+#
+# watch_a_file.perl -- use lsof -F output to watch a specific file
+# (or file system)
+#
+# usage: watch_a_file.perl file_name
+
+## Interrupt handler
+
+sub interrupt { wait; print "\n"; exit 0; }
+
+
+## Start main program
+
+$Pn = "watch_a_file";
+# Check file argument.
+
+if ($#ARGV != 0) { print "$#ARGV\n"; die "$Pn usage: file_name\n"; }
+$fnm = $ARGV[0];
+if (! -r $fnm) { die "$Pn: can't read $fnm\n"; }
+
+# Do setup.
+
+$RPT = 15; # lsof repeat time
+$| = 1; # unbuffer output
+$SIG{'INT'} = 'interrupt'; # catch interrupt
+
+# Set path to lsof.
+
+if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first
+ if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH
+ print "can't execute $LSOF\n"; exit 1
+ }
+}
+
+# Read lsof -nPF output from a pipe and gather the PIDs of the processes
+# and file descriptors to watch.
+
+open(P, "$LSOF -nPFpf $fnm|") || die "$Pn: can't pipe to $LSOF\n";
+
+$curpid = -1;
+$pids = "";
+while (<P>) {
+ chop;
+ if (/^p(.*)/) { $curpid = $1; next; } # Identify process.
+ if (/^f/) {
+ if ($curpid > 0) {
+ if ($pids eq "") { $pids = $curpid; }
+ else { $pids = $pids . "," . $curpid; }
+ $curpid = -1;
+ }
+ }
+}
+close(P);
+wait;
+if ($pids eq "") { die "$Pn: no processes using $fnm located.\n"; }
+print "watch_file: $fnm being used by processes:\n\t$pids\n\n";
+
+# Read repeated lsof output from a pipe and display.
+
+$pipe = "$LSOF -ap $pids -r $RPT $fnm";
+open(P, "$pipe|") || die "$Pn: can't pipe: $pipe\n";
+
+while (<P>) { print $_; }
+close(P);
+print "$Pn: unexpected EOF from \"$pipe\"\n";
+exit 1;
+
+
+## isexec($path) -- is $path executable
+#
+# $path = absolute or relative path to file to test for executabiity.
+# Paths that begin with neither '/' nor '.' that arent't found as
+# simple references are also tested with the path prefixes of the
+# PATH environment variable.
+
+sub
+isexec {
+ my ($path) = @_;
+ my ($i, @P, $PATH);
+
+ $path =~ s/^\s+|\s+$//g;
+ if ($path eq "") { return(""); }
+ if (($path =~ m#^[\/\.]#)) {
+ if (-x $path) { return($path); }
+ return("");
+ }
+ $PATH = $ENV{PATH};
+ @P = split(":", $PATH);
+ for ($i = 0; $i <= $#P; $i++) {
+ if (-x "$P[$i]/$path") { return("$P[$i]/$path"); }
+ }
+ return("");
+}
diff --git a/scripts/xusers.awk b/scripts/xusers.awk
new file mode 100755
index 0000000..ac818b4
--- /dev/null
+++ b/scripts/xusers.awk
@@ -0,0 +1,137 @@
+#!/usr/bin/awk -f
+################################################################
+#
+# Program Name : xusers
+# Date Created : 02-27-97
+# Author : Dan A. Mercer
+# Email : damercer@mmm.com
+# :
+# Description : Print list of users and applications signed on
+# : X workstations
+################################################################
+# standard help message
+function help(hlpmsg) {
+basename = ARGV[0]
+sub(/.*\//,"",basename)
+printf "Format: %s [o=[hi]] [s=cdlp] [pattern]\n", basename
+print "Print list of users and applications signed on X workstations"
+print "NOTE: applicationname is truncated to 9 chars"
+print "Arguments:"
+print " o=[h|i] - Options"
+print " h - help - print this message"
+print " i - case insensitive pattern search"
+print " s=[c|d|l|p] - Sort Options"
+print " c - sort by command"
+print " d - sort by display name"
+print " l - sort by login name"
+print " p - sort by pid"
+print " pattern - regex pattern to search commands against"
+
+if (length(hlpmsg)) print hlpmsg
+exit
+}
+BEGIN {
+# process command line
+for (i=1;i<ARGC;i++) {
+ if (ARGV[i] ~ /^o=/) {
+ if (options)
+ help("duplicate option string")
+ options = ARGV[i]
+ sub(/^o=/,"",options)
+ if (options !~ /^[hi]$/)
+ help("Invalid options " options)
+ if ("h" == options)
+ help("")
+ else
+ igncase = 1
+ }
+ else if (ARGV[i] ~ /^s=/) {
+ if (sortorder)
+ help("duplicate sort order string")
+ sortorder = ARGV[i]
+ sub(/^s=/,"",sortorder)
+ if (sortorder !~ /^[cdlp]$/)
+ help("Invalid sort order: '" sortorder "'")
+ if ("p" == sortorder) {
+ sort = "sort -kn2"
+ }
+ else if ("c" == sortorder) {
+ # the 'b' option means ignore leading blanks
+ sort = "sort -kb3"
+ }
+ else if ("l" == sortorder) {
+ sort = "sort -kb1"
+ }
+ else {
+ sort = "sort -kb4"
+ }
+ }
+ else {
+ if (pattern)
+ help("duplicate pattern string")
+ pattern = ARGV[i]
+ }
+ }
+
+# default is to sort by pid
+sort = (sort) ? sort : "sort -kn2"
+
+# check for igncase
+if (pattern && igncase)
+ pattern = tolower(pattern)
+
+# set default pattern
+pattern = (pattern) ? pattern : ".*"
+
+cmd = "lsof -FpLcn -awP -iTCP:6000"
+# ||||| |||| |
+# ||||| |||| X servers use port 6000
+# ||||| |||don't list port names
+# ||||| ||suppress warning messages
+# ||||| |and all conditions
+# ||||| |options
+# |||||
+# ||||Internet addresses
+# |||command name
+# ||login name
+# |process id
+# Format string
+# Output consists of one record per pid, followed by newline
+# delimited fields for command, Login name, and network address
+# The pid is preceded by a 'p', command by a 'c',
+# Login name by an L, and network connection by an 'n'. There may
+# be multiple 'n' entries (for instance for vuewm)
+
+while ((cmd | getline field) > 0) {
+ type = substr(field,1,1)
+ sub("^.","",field)
+ if ("p" == type) {
+ # always output first
+ pid = field
+ PID[pid] = ++ct
+ }
+ else if ("c" == type) {
+ # always output second
+ XAPPL[pid] = field
+ }
+ else if ("L" == type) {
+ # always output fourth
+ USER[pid] = field
+ }
+ else if ("n" == type) {
+ # may be multiple instances - we just use the last
+ gsub(".*->|:6000","",field)
+ DPY[pid] = field
+ }
+ }
+close(cmd)
+
+printf "%8s %5s %-9s %s\n","USER","PID","COMMAND","DISPLAY"
+for (pid in PID) {
+ if (((igncase) ? tolower(XAPPL[pid]) : XAPPL[pid]) ~ pattern)
+ printf "%8s %5d %-9s %s\n", USER[pid],pid,XAPPL[pid],DPY[pid] | sort
+ }
+
+close(sort)
+exit
+}