| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::Connection::ncnetstat; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 2 |  |  | 2 |  | 214868 | use 5.006; | 
|  | 2 |  |  |  |  | 18 |  | 
| 4 | 2 |  |  | 2 |  | 12 | use strict; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 57 |  | 
| 5 | 2 |  |  | 2 |  | 11 | use warnings; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 59 |  | 
| 6 | 2 |  |  | 2 |  | 1159 | use Net::Connection; | 
|  | 2 |  |  |  |  | 216374 |  | 
|  | 2 |  |  |  |  | 174 |  | 
| 7 | 2 |  |  | 2 |  | 1224 | use Net::Connection::Match; | 
|  | 2 |  |  |  |  | 4596 |  | 
|  | 2 |  |  |  |  | 80 |  | 
| 8 | 2 |  |  | 2 |  | 1047 | use Net::Connection::Sort; | 
|  | 2 |  |  |  |  | 848 |  | 
|  | 2 |  |  |  |  | 81 |  | 
| 9 | 2 |  |  | 2 |  | 1445 | use Term::ANSIColor; | 
|  | 2 |  |  |  |  | 28287 |  | 
|  | 2 |  |  |  |  | 330 |  | 
| 10 | 2 |  |  | 2 |  | 1262 | use Proc::ProcessTable; | 
|  | 2 |  |  |  |  | 12390 |  | 
|  | 2 |  |  |  |  | 130 |  | 
| 11 | 2 |  |  | 2 |  | 2557 | use Text::ANSITable; | 
|  | 2 |  |  |  |  | 181027 |  | 
|  | 2 |  |  |  |  | 95 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | # use Net::Connection::FreeBSD_sockstat if possible | 
| 14 |  |  |  |  |  |  | #use if $^O eq 'freebsd', 'Net::Connection::FreeBSD_sockstat'; | 
| 15 |  |  |  |  |  |  | #use if $^O ne 'freebsd', 'Net::Connection::lsof'; | 
| 16 | 2 |  |  | 2 |  | 1152 | use Net::Connection::lsof; | 
|  | 2 |  |  |  |  | 3154 |  | 
|  | 2 |  |  |  |  | 3823 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | =head1 NAME | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | Net::Connection::ncnetstat - The backend for ncnetstat, the colorized and enhanced netstat like tool. | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | =head1 VERSION | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | Version 0.7.1 | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | =cut | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | our $VERSION = '0.7.1'; | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | use Net::Connection::ncnetstat; | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | # Net::Connection::Match filters | 
| 36 |  |  |  |  |  |  | my @filters=( | 
| 37 |  |  |  |  |  |  | { | 
| 38 |  |  |  |  |  |  | type=>'States', | 
| 39 |  |  |  |  |  |  | invert=>1, | 
| 40 |  |  |  |  |  |  | args=>{ | 
| 41 |  |  |  |  |  |  | states=>['LISTEN'] | 
| 42 |  |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | my $ncnetstat=Net::Connection::ncnetstat->new( | 
| 47 |  |  |  |  |  |  | { | 
| 48 |  |  |  |  |  |  | ptr=>1, | 
| 49 |  |  |  |  |  |  | command=>1, | 
| 50 |  |  |  |  |  |  | command_long=>0, | 
| 51 |  |  |  |  |  |  | wchan=>0, | 
| 52 |  |  |  |  |  |  | pct_show=>1, | 
| 53 |  |  |  |  |  |  | sorter=>{ | 
| 54 |  |  |  |  |  |  | invert=>0, | 
| 55 |  |  |  |  |  |  | type=>'host_lf', | 
| 56 |  |  |  |  |  |  | }, | 
| 57 |  |  |  |  |  |  | match=>{ | 
| 58 |  |  |  |  |  |  | checks=>\@filters, | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  | ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | print $ncnetstat->run; | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | =head1 METHODS | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | =head2 new | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | This initiates the object. | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | my $ncnetstat=Net::Connection::ncnetstat->new( \%args ); | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | =head3 args hash ref | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | =head4 command | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | If set to true, it will show the command for the PID. | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | =head4 command_long | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | If set to true, the full command is shown. | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | This requires command also being true. | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | =head4 match | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | This is the hash to pass to L<Net::Connection::Match>. | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | By default this is undef and that module won't be used. | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | =head4 no_pid_user | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | Don't show the PID or UID/user colomn. | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | =head4 sorter | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | This is what is to be passed to L<Net::Connection::Sorter>. | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | The default is as below. | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | { | 
| 102 |  |  |  |  |  |  | type=>'host_fl', | 
| 103 |  |  |  |  |  |  | invert=>0, | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | =cut | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | sub new { | 
| 109 | 0 |  |  | 0 | 1 |  | my %args; | 
| 110 | 0 | 0 |  |  |  |  | if ( defined( $_[1] ) ) { | 
| 111 | 0 |  |  |  |  |  | %args = %{ $_[1] }; | 
|  | 0 |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 0 | 0 |  |  |  |  | if ( !defined( $args{sorter} ) ) { | 
| 115 |  |  |  |  |  |  | $args{sorter} = { | 
| 116 | 0 |  |  |  |  |  | type   => 'host_fl', | 
| 117 |  |  |  |  |  |  | invert => 0, | 
| 118 |  |  |  |  |  |  | }; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | my $self = { | 
| 122 |  |  |  |  |  |  | invert       => 0, | 
| 123 | 0 |  |  |  |  |  | sorter       => Net::Connection::Sort->new( $args{sorter} ), | 
| 124 |  |  |  |  |  |  | ptr          => 1, | 
| 125 |  |  |  |  |  |  | command      => 0, | 
| 126 |  |  |  |  |  |  | command_long => 0, | 
| 127 |  |  |  |  |  |  | wchan        => 0, | 
| 128 |  |  |  |  |  |  | pct          => 0, | 
| 129 |  |  |  |  |  |  | no_pid_user  => 0, | 
| 130 |  |  |  |  |  |  | }; | 
| 131 | 0 |  |  |  |  |  | bless $self; | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 0 | 0 |  |  |  |  | if ( defined( $args{match} ) ) { | 
| 134 | 0 |  |  |  |  |  | $self->{match} = Net::Connection::Match->new( $args{match} ); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 0 | 0 |  |  |  |  | if ( defined( $args{ptr} ) ) { | 
| 138 | 0 |  |  |  |  |  | $self->{ptr} = $args{ptr}; | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 0 | 0 |  |  |  |  | if ( defined( $args{command} ) ) { | 
| 142 | 0 |  |  |  |  |  | $self->{command} = $args{command}; | 
| 143 |  |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 0 | 0 |  |  |  |  | if ( defined( $args{pct} ) ) { | 
| 146 | 0 |  |  |  |  |  | $self->{pct} = $args{pct}; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 | 0 | 0 |  |  |  |  | if ( defined( $args{wchan} ) ) { | 
| 150 | 0 |  |  |  |  |  | $self->{wchan} = $args{wchan}; | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  |  | 
| 153 | 0 | 0 |  |  |  |  | if ( defined( $args{command_long} ) ) { | 
| 154 | 0 |  |  |  |  |  | $self->{command_long} = $args{command_long}; | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 0 | 0 |  |  |  |  | if ( defined( $args{no_pid_user} ) ) { | 
| 158 | 0 |  |  |  |  |  | $self->{no_pid_user} = $args{no_pid_user}; | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 0 |  |  |  |  |  | return $self; | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | =head2 run | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | This runs it and returns a string. | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | print $ncnetstat->run; | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | =cut | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | sub run { | 
| 173 | 0 |  |  | 0 | 1 |  | my $self = $_[0]; | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 0 |  |  |  |  |  | my @objects; | 
| 176 |  |  |  |  |  |  | #	if ( $^O !~ /freebsd/ ) { | 
| 177 | 0 |  |  |  |  |  | @objects = &lsof_to_nc_objects; | 
| 178 |  |  |  |  |  |  | #	} | 
| 179 |  |  |  |  |  |  | #	else { | 
| 180 |  |  |  |  |  |  | #		@objects = &sockstat_to_nc_objects; | 
| 181 |  |  |  |  |  |  | #	} | 
| 182 |  |  |  |  |  |  |  | 
| 183 | 0 |  |  |  |  |  | my @found; | 
| 184 | 0 | 0 |  |  |  |  | if ( defined( $self->{match} ) ) { | 
| 185 | 0 |  |  |  |  |  | foreach my $conn (@objects) { | 
| 186 | 0 | 0 |  |  |  |  | if ( $self->{match}->match($conn) ) { | 
| 187 | 0 |  |  |  |  |  | push( @found, $conn ); | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  | } | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  | else { | 
| 192 | 0 |  |  |  |  |  | @found = @objects; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 0 |  |  |  |  |  | @found = $self->{sorter}->sorter( \@found ); | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 0 |  |  |  |  |  | my $tb = Text::ANSITable->new; | 
| 198 | 0 |  |  |  |  |  | $tb->border_style('ASCII::None'); | 
| 199 | 0 |  |  |  |  |  | $tb->color_theme('NoColor'); | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 0 |  |  |  |  |  | my @headers; | 
| 202 | 0 |  |  |  |  |  | my $header_int = 0; | 
| 203 | 0 |  |  |  |  |  | push( @headers, 'Proto' ); | 
| 204 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 0 ); | 
| 205 | 0 |  |  |  |  |  | $header_int++; | 
| 206 | 0 | 0 |  |  |  |  | if ( !$self->{no_pid_user} ) { | 
| 207 | 0 |  |  |  |  |  | push( @headers, 'User' ); | 
| 208 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 1 ); | 
| 209 | 0 |  |  |  |  |  | $header_int++; | 
| 210 | 0 |  |  |  |  |  | push( @headers, 'PID' ); | 
| 211 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 0 ); | 
| 212 | 0 |  |  |  |  |  | $header_int++; | 
| 213 |  |  |  |  |  |  | } | 
| 214 | 0 |  |  |  |  |  | push( @headers, 'Local Host' ); | 
| 215 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] ); | 
| 216 | 0 |  |  |  |  |  | $header_int++; | 
| 217 | 0 |  |  |  |  |  | push( @headers, 'L Port' ); | 
| 218 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 0 ); | 
| 219 | 0 |  |  |  |  |  | $header_int++; | 
| 220 | 0 |  |  |  |  |  | push( @headers, 'Remote Host' ); | 
| 221 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] ); | 
| 222 | 0 |  |  |  |  |  | $header_int++; | 
| 223 | 0 |  |  |  |  |  | push( @headers, 'R Port' ); | 
| 224 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 0 ); | 
| 225 | 0 |  |  |  |  |  | $header_int++; | 
| 226 | 0 |  |  |  |  |  | push( @headers, 'State' ); | 
| 227 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => 1 ); | 
| 228 | 0 |  |  |  |  |  | $header_int++; | 
| 229 |  |  |  |  |  |  |  | 
| 230 | 0 |  |  |  |  |  | my $padding = 0; | 
| 231 | 0 | 0 |  |  |  |  | if ( $self->{wchan} ) { | 
| 232 | 0 | 0 |  |  |  |  | if ( ( $header_int % 2 ) != 0 ) { | 
| 233 | 0 |  |  |  |  |  | $padding = 1; | 
| 234 |  |  |  |  |  |  | } | 
| 235 | 0 |  |  |  |  |  | push( @headers, 'WChan' ); | 
| 236 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => $padding ); | 
| 237 | 0 |  |  |  |  |  | $header_int++; | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  |  | 
| 240 | 0 | 0 |  |  |  |  | if ( $self->{pct} ) { | 
| 241 | 0 | 0 |  |  |  |  | if ( ( $header_int % 2 ) != 0 ) { | 
| 242 | 0 |  |  |  |  |  | $padding = 1; | 
| 243 |  |  |  |  |  |  | } | 
| 244 |  |  |  |  |  |  | else { | 
| 245 | 0 |  |  |  |  |  | $padding = 0; | 
| 246 |  |  |  |  |  |  | } | 
| 247 | 0 |  |  |  |  |  | push( @headers, 'CPU%' ); | 
| 248 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => $padding ); | 
| 249 | 0 |  |  |  |  |  | $header_int++; | 
| 250 | 0 | 0 |  |  |  |  | if ( ( $header_int % 2 ) != 0 ) { | 
| 251 | 0 |  |  |  |  |  | $padding = 1; | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | else { | 
| 254 | 0 |  |  |  |  |  | $padding = 0; | 
| 255 |  |  |  |  |  |  | } | 
| 256 | 0 |  |  |  |  |  | push( @headers, 'Mem%' ); | 
| 257 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => $padding ); | 
| 258 | 0 |  |  |  |  |  | $header_int++; | 
| 259 |  |  |  |  |  |  | } | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 0 | 0 |  |  |  |  | if ( $self->{command} ) { | 
| 262 | 0 | 0 |  |  |  |  | if ( ( $header_int % 2 ) != 0 ) { | 
| 263 | 0 |  |  |  |  |  | $padding = 1; | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | else { | 
| 266 | 0 |  |  |  |  |  | $padding = 0; | 
| 267 |  |  |  |  |  |  | } | 
| 268 | 0 |  |  |  |  |  | push( @headers, 'Command' ); | 
| 269 | 0 |  |  |  |  |  | $tb->set_column_style( $header_int, pad => $padding, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] ); | 
| 270 | 0 |  |  |  |  |  | $header_int++; | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | 
| 273 | 0 |  |  |  |  |  | $tb->set_column_style( 4,  pad => 0 ); | 
| 274 | 0 |  |  |  |  |  | $tb->set_column_style( 5,  pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] ); | 
| 275 | 0 |  |  |  |  |  | $tb->set_column_style( 6,  pad => 0 ); | 
| 276 | 0 |  |  |  |  |  | $tb->set_column_style( 7,  pad => 1 ); | 
| 277 | 0 |  |  |  |  |  | $tb->set_column_style( 8,  pad => 0 ); | 
| 278 | 0 |  |  |  |  |  | $tb->set_column_style( 9,  pad => 1 ); | 
| 279 | 0 |  |  |  |  |  | $tb->set_column_style( 10, pad => 0 ); | 
| 280 | 0 |  |  |  |  |  | $tb->set_column_style( 11, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] ); | 
| 281 | 0 |  |  |  |  |  | $tb->set_column_style( 12, pad => 0 ); | 
| 282 | 0 |  |  |  |  |  | $tb->set_column_style( 13, pad => 1 ); | 
| 283 |  |  |  |  |  |  |  | 
| 284 | 0 |  |  |  |  |  | $tb->columns( \@headers ); | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | # process table stuff if needed | 
| 287 | 0 |  |  |  |  |  | my $ppt; | 
| 288 |  |  |  |  |  |  | my $proctable; | 
| 289 | 0 |  |  |  |  |  | my %cmd_cache; | 
| 290 | 0 | 0 |  |  |  |  | if ( $self->{command} ) { | 
| 291 | 0 |  |  |  |  |  | $ppt       = Proc::ProcessTable->new; | 
| 292 | 0 |  |  |  |  |  | $proctable = $ppt->table; | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  |  | 
| 295 | 0 |  |  |  |  |  | my @td; | 
| 296 | 0 |  |  |  |  |  | foreach my $conn (@found) { | 
| 297 | 0 |  |  |  |  |  | my @new_line = ( color('bright_yellow') . $conn->proto . color('reset'), ); | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | # don't add the PID or user if requested to | 
| 300 | 0 | 0 |  |  |  |  | if ( !$self->{no_pid_user} ) { | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | # handle adding the username or UID if we have one | 
| 303 | 0 | 0 |  |  |  |  | if ( defined( $conn->username ) ) { | 
| 304 | 0 |  |  |  |  |  | push( @new_line, color('bright_cyan') . $conn->username . color('reset') ); | 
| 305 |  |  |  |  |  |  | } | 
| 306 |  |  |  |  |  |  | else { | 
| 307 | 0 | 0 |  |  |  |  | if ( defined( $conn->uid ) ) { | 
| 308 | 0 |  |  |  |  |  | push( @new_line, color('bright_cyan') . $conn->uid . color('reset') ); | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  | else { | 
| 311 | 0 |  |  |  |  |  | push( @new_line, '' ); | 
| 312 |  |  |  |  |  |  | } | 
| 313 |  |  |  |  |  |  | } | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | # handle adding the PID if we have one | 
| 316 | 0 | 0 |  |  |  |  | if ( defined( $conn->pid ) ) { | 
| 317 | 0 |  |  |  |  |  | push( @new_line, color('bright_red') . $conn->pid . color('reset') ); | 
| 318 | 0 |  |  |  |  |  | $conn->pid; | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | else { | 
| 321 | 0 |  |  |  |  |  | push( @new_line, '' ); | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | # Figure out what we are using for the local host | 
| 326 | 0 |  |  |  |  |  | my $local; | 
| 327 | 0 | 0 | 0 |  |  |  | if ( defined( $conn->local_ptr ) && $self->{ptr} ) { | 
| 328 | 0 |  |  |  |  |  | $local = $conn->local_ptr; | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  | else { | 
| 331 | 0 |  |  |  |  |  | $local = $conn->local_host; | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | # Figure out what we are using for the foriegn host | 
| 335 | 0 |  |  |  |  |  | my $foreign; | 
| 336 | 0 | 0 | 0 |  |  |  | if ( defined( $conn->foreign_ptr ) && $self->{ptr} ) { | 
| 337 | 0 |  |  |  |  |  | $foreign = $conn->foreign_ptr; | 
| 338 |  |  |  |  |  |  | } | 
| 339 |  |  |  |  |  |  | else { | 
| 340 | 0 |  |  |  |  |  | $foreign = $conn->foreign_host; | 
| 341 |  |  |  |  |  |  | } | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | # Figure out what we are using for the local port | 
| 344 | 0 |  |  |  |  |  | my $lport; | 
| 345 | 0 | 0 |  |  |  |  | if ( defined( $conn->local_port_name ) ) { | 
| 346 | 0 |  |  |  |  |  | $lport = $conn->local_port_name; | 
| 347 |  |  |  |  |  |  | } | 
| 348 |  |  |  |  |  |  | else { | 
| 349 | 0 |  |  |  |  |  | $lport = $conn->local_port; | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | # Figure out what we are using for the foreign port | 
| 353 | 0 |  |  |  |  |  | my $fport; | 
| 354 | 0 | 0 |  |  |  |  | if ( defined( $conn->foreign_port_name ) ) { | 
| 355 | 0 |  |  |  |  |  | $fport = $conn->foreign_port_name; | 
| 356 |  |  |  |  |  |  | } | 
| 357 |  |  |  |  |  |  | else { | 
| 358 | 0 |  |  |  |  |  | $fport = $conn->foreign_port; | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  |  | 
| 361 | 0 |  |  |  |  |  | push( @new_line, | 
| 362 |  |  |  |  |  |  | color('bright_green') . $local . color('reset'), | 
| 363 |  |  |  |  |  |  | color('green') . $lport . color('reset'), | 
| 364 |  |  |  |  |  |  | color('bright_magenta') . $foreign . color('reset'), | 
| 365 |  |  |  |  |  |  | color('magenta') . $fport . color('reset'), | 
| 366 |  |  |  |  |  |  | color('bright_blue') . $conn->state . color('reset'), | 
| 367 |  |  |  |  |  |  | ); | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  | # handle the wchan bit if needed | 
| 370 | 0 | 0 | 0 |  |  |  | if ( $self->{wchan} | 
| 371 |  |  |  |  |  |  | && defined( $conn->wchan ) ) | 
| 372 |  |  |  |  |  |  | { | 
| 373 | 0 |  |  |  |  |  | push( @new_line, color('bright_yellow') . $conn->wchan . color('reset') ); | 
| 374 |  |  |  |  |  |  | } | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | # handle the percent stuff if needed | 
| 377 | 0 | 0 | 0 |  |  |  | if ( $self->{pct} | 
| 378 |  |  |  |  |  |  | && defined( $conn->pctcpu ) ) | 
| 379 |  |  |  |  |  |  | { | 
| 380 | 0 |  |  |  |  |  | push( @new_line, color('bright_cyan') . sprintf( '%.2f', $conn->pctcpu ) . color('reset') ); | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | # handle the percent stuff if needed | 
| 384 | 0 | 0 | 0 |  |  |  | if ( $self->{pct} | 
| 385 |  |  |  |  |  |  | && defined( $conn->pctmem ) ) | 
| 386 |  |  |  |  |  |  | { | 
| 387 | 0 |  |  |  |  |  | push( @new_line, color('bright_green') . sprintf( '%.2f', $conn->pctmem ) . color('reset') ); | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | # handle the command portion if needed | 
| 391 | 0 | 0 | 0 |  |  |  | if ( defined( $conn->pid ) | 
|  |  | 0 | 0 |  |  |  |  | 
| 392 |  |  |  |  |  |  | && $self->{command} ) | 
| 393 |  |  |  |  |  |  | { | 
| 394 |  |  |  |  |  |  |  | 
| 395 | 0 |  |  |  |  |  | my $loop = 1; | 
| 396 | 0 |  |  |  |  |  | my $proc = 0; | 
| 397 | 0 |  | 0 |  |  |  | while ( defined( $proctable->[$proc] ) | 
| 398 |  |  |  |  |  |  | && $loop ) | 
| 399 |  |  |  |  |  |  | { | 
| 400 | 0 |  |  |  |  |  | my $command; | 
| 401 | 0 | 0 |  |  |  |  | if ( defined( $cmd_cache{ $conn->pid } ) ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 402 | 0 |  |  |  |  |  | push( @new_line, color('bright_red') . $cmd_cache{ $conn->pid } . color('reset') ); | 
| 403 | 0 |  |  |  |  |  | $loop = 0; | 
| 404 |  |  |  |  |  |  | } | 
| 405 |  |  |  |  |  |  | elsif ( defined( $conn->proc ) ) { | 
| 406 | 0 |  |  |  |  |  | my $command = $conn->proc; | 
| 407 | 0 | 0 |  |  |  |  | if ( !$self->{command_long} ) { | 
| 408 | 0 |  |  |  |  |  | $command =~ s/\ .*//; | 
| 409 |  |  |  |  |  |  | } | 
| 410 | 0 |  |  |  |  |  | $cmd_cache{ $conn->pid } = $command; | 
| 411 | 0 |  |  |  |  |  | push( @new_line, color('bright_red') . $cmd_cache{ $conn->pid } . color('reset') ); | 
| 412 | 0 |  |  |  |  |  | $loop = 0,; | 
| 413 |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  | elsif ( $proctable->[$proc]->pid eq $conn->pid ) { | 
| 415 | 0 | 0 |  |  |  |  | if ( $proctable->[$proc]->{'cmndline'} =~ /^$/ ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | #kernel process | 
| 418 |  |  |  |  |  |  | $cmd_cache{ $conn->pid } | 
| 419 | 0 |  |  |  |  |  | = color('bright_red') . '[' . $proctable->[$proc]->{'fname'} . ']' . color('reset'); | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  | elsif ( $self->{command_long} ) { | 
| 422 |  |  |  |  |  |  | $cmd_cache{ $conn->pid } | 
| 423 | 0 |  |  |  |  |  | = color('bright_red') . $proctable->[$proc]->{'cmndline'} . color('reset'); | 
| 424 |  |  |  |  |  |  | } | 
| 425 |  |  |  |  |  |  | elsif ( $proctable->[$proc]->{'cmndline'} =~ /^\// ) { | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | # something ran with a complete path | 
| 428 |  |  |  |  |  |  | $cmd_cache{ $conn->pid } | 
| 429 | 0 |  |  |  |  |  | = color('bright_red') . $proctable->[$proc]->{'fname'} . color('reset'); | 
| 430 |  |  |  |  |  |  | } | 
| 431 |  |  |  |  |  |  | else { | 
| 432 |  |  |  |  |  |  | # likely a thread or the like... such as dovecot/auth | 
| 433 |  |  |  |  |  |  | # just trunkcat everything after the space | 
| 434 | 0 |  |  |  |  |  | my $cmd = $proctable->[$proc]->{'cmndline'}; | 
| 435 | 0 |  |  |  |  |  | $cmd =~ s/\ +.*//g; | 
| 436 | 0 |  |  |  |  |  | $cmd_cache{ $conn->pid } = color('bright_red') . $cmd . color('reset'); | 
| 437 |  |  |  |  |  |  | } | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 0 |  |  |  |  |  | push( @new_line, $cmd_cache{ $conn->pid } ); | 
| 440 | 0 |  |  |  |  |  | $loop = 0; | 
| 441 |  |  |  |  |  |  | } | 
| 442 |  |  |  |  |  |  |  | 
| 443 | 0 |  |  |  |  |  | $proc++; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | } | 
| 447 |  |  |  |  |  |  | elsif ( ( !defined( $conn->pid ) ) | 
| 448 |  |  |  |  |  |  | && $self->{command} ) | 
| 449 |  |  |  |  |  |  | { | 
| 450 | 0 |  |  |  |  |  | push( @new_line, '' ); | 
| 451 |  |  |  |  |  |  | } | 
| 452 |  |  |  |  |  |  |  | 
| 453 | 0 |  |  |  |  |  | $tb->add_row( \@new_line ); | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  |  | 
| 456 | 0 |  |  |  |  |  | return $tb->draw; | 
| 457 |  |  |  |  |  |  | } | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | =head1 TODO | 
| 460 |  |  |  |  |  |  |  | 
| 461 |  |  |  |  |  |  | * Add support for more collection methods than L<Net::Connection::lsof> | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  | * Support color selection and column ordering. | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | =head1 AUTHOR | 
| 466 |  |  |  |  |  |  |  | 
| 467 |  |  |  |  |  |  | Zane C. Bowers-Hadley, C<< <vvelox at vvelox.net> >> | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | =head1 BUGS | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | Please report any bugs or feature requests to C<bug-net-connection-ncnetstat at rt.cpan.org>, or through | 
| 472 |  |  |  |  |  |  | the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Connection-ncnetstat>.  I will be notified, and then you'll | 
| 473 |  |  |  |  |  |  | automatically be notified of progress on your bug as I make changes. | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | =head1 SUPPORT | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | You can find documentation for this module with the perldoc command. | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | perldoc Net::Connection::ncnetstat | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | You can also look for information at: | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | =over 4 | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | =item * RT: CPAN's request tracker (report bugs here) | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Connection-ncnetstat> | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | =item * AnnoCPAN: Annotated CPAN documentation | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | L<http://annocpan.org/dist/Net-Connection-ncnetstat> | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | =item * CPAN Ratings | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | L<https://cpanratings.perl.org/d/Net-Connection-ncnetstat> | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | =item * Search CPAN | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  | L<https://metacpan.org/release/Net-Connection-ncnetstat> | 
| 504 |  |  |  |  |  |  |  | 
| 505 |  |  |  |  |  |  | =item * Repository | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  | L<https://github.com/VVelox/Net-Connection-ncnetstat> | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | =back | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | =head1 ACKNOWLEDGEMENTS | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | =head1 LICENSE AND COPYRIGHT | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | This software is Copyright (c) 2019 by Zane C. Bowers-Hadley. | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | This is free software, licensed under: | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | The Artistic License 2.0 (GPL Compatible) | 
| 522 |  |  |  |  |  |  |  | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | =cut | 
| 525 |  |  |  |  |  |  |  | 
| 526 |  |  |  |  |  |  | 1; # End of Net::Connection::ncnetstat |