diff options
author | Patrick McCarty <patrick.mccarty@linux.intel.com> | 2013-02-08 13:26:27 -0800 |
---|---|---|
committer | Patrick McCarty <patrick.mccarty@linux.intel.com> | 2013-02-08 13:26:27 -0800 |
commit | 9bb81f8a90ecc8b70c955bff72ec59dd3d9e5ae7 (patch) | |
tree | 881eebfa461e4f8aa6b6f44b96ac0decd3bc887a /scripts | |
download | lsof-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/00MANIFEST | 58 | ||||
-rw-r--r-- | scripts/00README | 55 | ||||
-rwxr-xr-x | scripts/big_brother.perl5 | 210 | ||||
-rwxr-xr-x | scripts/count_pf.perl | 68 | ||||
-rwxr-xr-x | scripts/count_pf.perl5 | 94 | ||||
-rwxr-xr-x | scripts/identd.perl5 | 131 | ||||
-rwxr-xr-x | scripts/idrlogin.perl | 201 | ||||
-rwxr-xr-x | scripts/idrlogin.perl5 | 197 | ||||
-rwxr-xr-x | scripts/list_NULf.perl5 | 161 | ||||
-rw-r--r-- | scripts/list_fields.awk | 198 | ||||
-rwxr-xr-x | scripts/list_fields.perl | 156 | ||||
-rwxr-xr-x | scripts/shared.perl5 | 409 | ||||
-rwxr-xr-x | scripts/sort_res.perl5 | 135 | ||||
-rwxr-xr-x | scripts/watch_a_file.perl | 94 | ||||
-rwxr-xr-x | scripts/xusers.awk | 137 |
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 "# ", ×tamp, " $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 "# ", ×tamp, " 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 "# ", ×tamp, "\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 +} |