#!/usr/bin/env perl # (C) Pavel Polyakov bsd@kobyla.org 2020 our $has_sysctl=0; use Carp 'croak'; use version; sub require1 { my ($filename) = @_; if ( my $version = eval { version->parse($filename) } ) { if ( $version > $^V ) { my $vn = $version->normal; croak "Perl $vn required--this is only $^V, stopped"; } return 1; } if (exists $INC{$filename}) { return 1 if $INC{$filename}; croak "Compilation failed in require"; } foreach $prefix (@INC) { if (ref($prefix)) { #... do other stuff - see text below .... } # (see text below about possible appending of .pmc # suffix to $filename) my $realfilename = "$prefix/$filename"; next if ! -e $realfilename || -d _ || -b _; $INC{$filename} = $realfilename; my $result = do($realfilename); # but run in caller's namespace if (!defined $result) { $INC{$filename} = undef; croak $@ ? "$@Compilation failed in require" : "Can't locate $filename: $!\n"; } if (!$result) { delete $INC{$filename}; croak "$filename did not return true value"; } $! = 0; return $result; } #print "Can't locate $filename in \@INC ...\n"; return 0; } if(require1 'BSD/Sysctl.pm') {; #print "$!\n"; BSD::Sysctl->import(qw/sysctl sysctl_description/); #print sysctl('kern.lastpid'); $has_sysctl=1; } sub arg1(){ my $a=shift @ARGV; return $a; } sub parse_sysctl { my $ref_str = shift; my $ref_hash = shift; my $name=undef; my $val=undef; for(split /[\r\n]+/s, $$ref_str) { if(/^([a-z][a-z0-9._%-]+):\s(.*)$/i) { $name=$1; $val=$2; #print "\t\t$name = $val\n"; $$ref_hash{$name} = $val; } elsif(/^\s+(.*)$/i) { $$ref_hash{$name} .= "\n\t$1"; } else { $$ref_hash{$name} .= "\n\t$_"; # !!! #print STDERR "??? $name ??? $_\n"; } } } sub get_sysctl { my $key=shift; my $val; if($has_sysctl) { $val=sysctl($key); #print "$key: $val\n"; goto no_sct if ref $val || $val=~/\x00/; } else { no_sct: $val=`$sysctl -n "$key"`; } chomp $val; return $val; } our $max_name=0; our $max_val=0; our $total=0; sub print_sysctl { my $key=shift; my $desc=$desc{$key}; my $val =$val{$key}; my $is_multiline = $val=~/\n/s || $print_desc && $desc=~/\n/s; if($print_table && !$is_multiline) { if($print_desc) { printf "%-${max_name}s : %${max_val}s : %s\n", $key, $val, $desc; } else { printf "%-${max_name}s : %${max_val}s\n", $key, $val; } } else { if($print_desc) { print "$key : ", $val, " : ", $desc, "\n"; } else { print "$key: ", $val, "\n"; } } print "\n" if($print_multiline && $is_multiline); $total++; } our %val = (); our %desc = (); my $w_name=50; my $w_val=50; my $verbose=0; my $only_single=0; my $show_opaque=0; my $search_desc=0; my @search_tree=(); #my $cmd=undef; my $help="Usage: $0 [options] [\@tree [\@tree]] [options] List specified sysctl values (with description) \@tree Start looking variables at the specified sysctl tree(s) -a All sysctls (. pattern) -o Include opaque values -1 Only single lined values -d Include description in output -D Search in description either -m Separate multiline values with the blank line -s Print stats -t Table output BSD:Sysctl sysutils/p5-BSD-Sysctl can be installed for the better performance "; while(defined ($_=arg1())) { if(/^-+(.*)/) { my $arg=$1; if($print_table += $arg=~s/t//g) { } if($print_stats += $arg=~s/s//g) { } if($print_multiline += $arg=~s/m//g) { } if($print_desc += $arg=~s/d//g) { } if($search_desc += $arg=~s/D//g) { } if($verbose += $arg=~s/v//g) { } if($only_single += $arg=~s/1//g) { } if($show_opaque += $arg=~s/o//g) { } if($arg=~s/a//g) { $grep='.'; } if($arg ne '') { #$cmd='help'; help: print $help; exit 64; } } elsif(/^\@(.*)$/) { push @search_tree, $1; } else { $grep=$_; } } #print "grep: $grep\n"; no warnings 'deprecated'; goto help unless defined $grep; print STDERR "has_bsd_sysctl = $has_sysctl\n" if $verbose; our $sysctl=`\\which sysctl`; chomp $sysctl; if($sysctl eq '') { print STDERR "Error! Cant find sysctl utility\n"; exit 69; } if ($show_opaque || $grep=~/hostcache\.list/) { $desc{'net.inet.tcp.hostcache.list'} = 'List of all hostcache entries (opaque)'; }; #$sct = ` sysctl -a|egrep -v "^[|^<.>|^<...>"|egrep "$grep" ` #$sdt = ` sysctl -a|egrep "$grep" ` #$sct = `sysctl -a`; $sdt = join(' ',@search_tree); $sdt = `$sysctl -ad $sdt`; parse_sysctl(\$sdt, \%desc); if (!$show_opaque) { delete $desc{'kern.msgbuf'}; }; #print "\n"; #print keys %desc; #print "net.inet.tcp.rexmit_min = ",$desc{'net.inet.tcp.rexmit_min'}, "\n"; my @res_single=(); my @res_multi=(); my $key; for $key (sort keys %desc) { if($key =~ /$grep/i || $search_desc && $desc{$key} =~ /$grep/ ) { my $val = get_sysctl($key); $val{$key}=$val; my $desc=$desc{$key}; my $is_multiline = $val=~/\n/s || $print_desc && $desc=~/\n/s; if($is_multiline) { if(!$only_single) { push @res_multi, $key; }; } else { push @res_single, $key; $max_name = length($key) if(length($key) > $max_name); $max_val = length($val) if(length($val) > $max_val); } #print_sysctl($key); } } for $key (@res_single) { print_sysctl($key); } print "\n" if scalar @res_multi && $print_multiline; for $key (@res_multi) { print_sysctl($key); } if($print_stats) { print STDERR "Total $total variables listed\n"; } # pkg install sysutils/p5-BSD-Sysctl