diff options
author | des <des@FreeBSD.org> | 2000-10-07 14:10:37 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2000-10-07 14:10:37 +0000 |
commit | 35a375ea90f83fec3c572aa2bc8c481bef86a9db (patch) | |
tree | 286f89ec54fc561cd7113c41ec5a9695a0703799 /usr.bin | |
parent | 2f43c7014124bbdab8d84f8af679c287f2198aa9 (diff) | |
download | FreeBSD-src-35a375ea90f83fec3c572aa2bc8c481bef86a9db.zip FreeBSD-src-35a375ea90f83fec3c572aa2bc8c481bef86a9db.tar.gz |
Total rewrite. This was actually the first non-trivial Perl script I ever
wrote, and as such was not very pretty.
Changes that may cause problems for people who use sockstat in scripts:
- sockstat(8) now displays Unix domain sockets in addition to IPv4 and IPv6
- the last period in local and foreign addresses is changed to a colon to
make the port number easier to spot
- IPv4 and IPv6 sockets are listed separately (IPv4 first, then IPv6, then
Unix)
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/sockstat/sockstat.pl | 155 |
1 files changed, 129 insertions, 26 deletions
diff --git a/usr.bin/sockstat/sockstat.pl b/usr.bin/sockstat/sockstat.pl index 0ec2670..a6223ac 100644 --- a/usr.bin/sockstat/sockstat.pl +++ b/usr.bin/sockstat/sockstat.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl5 +#!/usr/bin/perl -w #- # Copyright (c) 1999 Dag-Erling Coïdan Smørgrav # All rights reserved. @@ -29,37 +29,140 @@ # $FreeBSD$ # -my (%proto, %myaddr, %hisaddr); -my ($user, $cmd, $pid, $fd, $inet, $type, $proto, $sock, $laddr, $faddr); +use strict; +use Getopt::Std; -print <<EOH; -USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS -EOH -format STDOUT = -@<<<<<<< @<<<<<<< @>>>> @>>> @<<<<< @<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<< -$user, $cmd, $pid, $fd, $proto,$laddr, $faddr -. +my %netstat; +my %fstat; +my $unknown = [ "?", "?", "?", "?", "?", "?", "?", "?", "?" ]; -open NETSTAT, "/usr/bin/netstat -Aan |" or die "'netstat' failed: $!"; -<NETSTAT>; <NETSTAT>; +my $inet_fmt = "%-8.8s %-8.8s %5.5s %4.4s %-6.6s %-21.21s %-21.21s\n"; +my $unix_fmt = "%-8.8s %-8.8s %5.5s %4.4s %-6.6s %-43.43s\n"; -while (<NETSTAT>) { - my ($sock, $proto, $recvq, $sendq, $laddr, $faddr, $state) = split; - ($proto{$sock}, $myaddr{$sock}, $hisaddr{$sock}) = - ($proto, $laddr, $faddr); +# +# Gather information about sockets +# +sub gather() { + + local *PIPE; # Pipe + my $pid; # Child PID + my $line; # Input line + my @fields; # Fields + + # Netstat + if (!defined($pid = open(PIPE, "-|"))) { + die("open(netstat): $!\n"); + } elsif ($pid == 0) { + exec("/usr/bin/netstat", "-Aan"); + die("exec(netstat): $!\n"); + } + while ($line = <PIPE>) { + next unless ($line =~ m/^[0-9a-f]{8} /); + chomp($line); + @fields = split(' ', $line); + $netstat{$fields[0]} = [ @fields ]; + } + close(PIPE) + or die("close(netstat): $!\n"); + + # Fstat + if (!defined($pid = open(PIPE, "-|"))) { + die("open(fstat): $!\n"); + } elsif ($pid == 0) { + exec("/usr/bin/fstat"); + die("exec(fstat): $!\n"); + } + while ($line = <PIPE>) { + chomp($line); + @fields = split(' ', $line); + next if ($fields[4] eq "-"); + push(@{$fstat{$fields[4]}}, [ @fields ]); + } + close(PIPE) + or die("close(fstat): $!\n"); } -close NETSTAT; +# +# Replace the last dot in an "address.port" string with a colon +# +sub addr($) { + my $addr = shift; # Address -open FSTAT, "/usr/bin/fstat |" or die "'fstat' failed: $!\n"; + $addr =~ s/^(.*)\.([^\.]*)$/$1:$2/; + return $addr; +} -while (<FSTAT>) { - ($user, $cmd, $pid, $fd, $inet, $type, $proto, $sock) = split; - chop $fd; - next unless ($inet eq "internet") || ($inet eq "internet6") && ($type ne "raw"); - ($proto, $laddr, $faddr) = - ($proto{$sock}, $myaddr{$sock}, $hisaddr{$sock}); - write STDOUT; +# +# Print information about Internet sockets +# +sub print_inet($) { + my $af = shift; # Address family + + my $fsd; # Fstat data + my $nsd; # Netstat data + + printf($inet_fmt, "USER", "COMMAND", "PID", "FD", + "PROTO", "LOCAL ADDRESS", "FOREIGN ADDRESS"); + foreach $fsd (@{$fstat{$af}}) { + $nsd = $netstat{$fsd->[7]} || $unknown; + printf($inet_fmt, $fsd->[0], $fsd->[1], $fsd->[2], + substr($fsd->[3], 0, -1), + $nsd->[1], addr($nsd->[4]), addr($nsd->[5])); + } + print("\n"); } -close FSTAT; +# +# Print information about Unix domain sockets +# +sub print_unix() { + + my %endpoint; # Mad PCB to process/fd + my $fsd; # Fstat data + my $nsd; # Netstat data + + foreach $fsd (@{$fstat{"local"}}) { + $endpoint{$fsd->[6]} = "$fsd->[1]\[$fsd->[2]\]:" . + substr($fsd->[3], 0, -1); + } + printf($unix_fmt, "USER", "COMMAND", "PID", "FD", "PROTO", "ADDRESS"); + foreach $fsd (@{$fstat{"local"}}) { + $nsd = $netstat{$fsd->[6]} || $unknown; + printf($unix_fmt, $fsd->[0], $fsd->[1], $fsd->[2], + substr($fsd->[3], 0, -1), $fsd->[5], + $nsd->[8] || ($fsd->[8] ? $endpoint{$fsd->[8]} : "(none)")); + } + print("\n"); +} + +# +# Print usage message and exit +# +sub usage() { + print(STDERR "Usage: sockstat [-46u]\n"); + exit(1); +} + +MAIN:{ + my %opts; # Command-line options + + getopts("46u", \%opts) + or usage(); + + gather(); + + if (!$opts{'4'} && !$opts{'6'} && !$opts{'u'}) { + $opts{'4'} = $opts{'6'} = $opts{'u'} = 1; + } + if ($opts{'4'}) { + print_inet("internet"); + } + if ($opts{'6'}) { + print_inet("internet6"); + } + if ($opts{'u'}) { + print_unix(); + } + + exit(0); +} |