From 59b57340b157755d635eb15432b995d086ee48e2 Mon Sep 17 00:00:00 2001
From: Gerhard Gonter <ggonter@gmail.com>
Date: Sun, 29 Oct 2023 08:56:05 +0100
Subject: [PATCH] added Parse::CMD::lsof and Parse::ZonedTables

---
 debian/control                    |  2 +-
 modules/util/Parse/CMD/lsof.pm    | 38 +++++++++++++
 modules/util/Parse/ZonedTables.pm | 94 +++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 modules/util/Parse/CMD/lsof.pm
 create mode 100644 modules/util/Parse/ZonedTables.pm

diff --git a/debian/control b/debian/control
index 17142f7..0c4bc6c 100644
--- a/debian/control
+++ b/debian/control
@@ -1,5 +1,5 @@
 Package: libgg-aix-pm-perl
-Version: 0.6-1
+Version: 0.7-1
 Architecture: all
 Maintainer: Gerhard Gonter <ggonter@gmail.com>
 Original-Maintainer: Gerhard Gonter <ggonter@gmail.com>
diff --git a/modules/util/Parse/CMD/lsof.pm b/modules/util/Parse/CMD/lsof.pm
new file mode 100644
index 0000000..603836d
--- /dev/null
+++ b/modules/util/Parse/CMD/lsof.pm
@@ -0,0 +1,38 @@
+
+package Parse::CMD::lsof;
+
+use strict;
+
+use Parse::ZonedTables;
+
+sub get_lsof_list
+{
+  open(LSOF, '-|', 'lsof') or die;
+  my $hdr= <LSOF>; chop($hdr);
+
+  # V1:
+  # my $fields= Parse::ZonedTables->new();
+  # $fields->get_fields($hdr);
+
+  # V2:
+  my $fields= Parse::ZonedTables->get_fields($hdr);
+
+  my @lines;
+  my %pids;
+  while (my $l= <LSOF>)
+  {
+    chop($l);
+    # print __LINE__, " lsof: l=[$l]\n";
+    my $rec= $fields->match_fields($l);
+    $rec->{_line}= $l; $rec->{_head}= $hdr; # used for debugging
+    # print __LINE__, " rec: ", Dumper($rec);
+    push (@lines, $rec);
+    push (@{$pids{$rec->{PID}}->{$rec->{TID}}} => $rec);
+  }
+  close(LSOF);
+
+  (\@lines, \%pids);
+}
+
+1;
+
diff --git a/modules/util/Parse/ZonedTables.pm b/modules/util/Parse/ZonedTables.pm
new file mode 100644
index 0000000..709248f
--- /dev/null
+++ b/modules/util/Parse/ZonedTables.pm
@@ -0,0 +1,94 @@
+
+package Parse::ZonedTables;
+
+# TODO: this is not a good nme, find something better!
+
+use strict;
+
+# use Data::Dumper;
+
+sub new
+{
+  my $class= shift;
+  my $self= bless({}, $class);
+  $self;
+}
+
+sub get_fields
+{
+  my $self= shift;
+  my $header= shift;
+
+  my $r= ref($self);
+  # print __LINE__, " r=[$r] self=[$self]\n";
+  $self= new($self) if ($r eq '');
+
+  my $lng= length($header);
+  my $st= 0;
+  my $word;
+  my @header= ();
+  my $field_num= 0;
+  for (my $i= 0; $i < $lng; $i++)
+  {
+    my $c= substr($header, $i, 1);
+    # print __LINE__, " i=[$i] c=[$c] st=[$st]\n";
+
+    if ($c ne ' ' && $st == 0) # new word
+    {
+      push(@header, $word= { label => $c, idx => $i, field_num => $field_num++ });
+      $st= 1;
+    }
+    elsif ($c ne ' ' && $st == 1) # next char of same wor
+    {
+      $word->{label} .= $c;
+    }
+    elsif ($c eq ' ' && $st == 1)
+    {
+      $st= 0;
+    }
+  }
+
+  # print __LINE__, " header: ", Dumper(\@header);
+
+  # (wantarray) ? @header : \@header;
+  $self->{fields}= \@header;
+
+  $self;
+}
+
+sub match_fields
+{
+  my $self= shift;
+  my $l= shift;
+
+  my $fields= $self->{fields};
+
+  my $last_field_num= $#$fields;
+  # print __LINE__, " last_field_num=[$last_field_num]\n";
+  # match fields right to lef
+  my $last_idx= length($l);
+  my %rec;
+  for (my $i= $last_field_num; $i >= 0; $i--)
+  {
+    my $f= $fields->[$i];
+    my ($idx, $label)= map { $f->{$_} } qw(idx label);
+
+    my $str= substr($l, $idx, $last_idx-$idx);
+    # there can be right-flushed fields, e.g. PID from lsof, so check, if there is something to the left of from the index of that label and add it to the string, if necessary
+    while ($idx > 0 && (my $x= substr($l, $idx-1, 1)) ne ' ')
+    {
+      $str= $x . $str;
+      $idx--;
+    }
+    $str =~ s#^ *##; $str =~ s# *$##; # remove padding blanks from the begin and end
+
+    $rec{$label}= $str;
+    # print __LINE__, " field i=[$i] idx=[$idx] last_idx=[$last_idx] label=[$label] str=[$str] f: ", Dumper($f);
+    $last_idx= $idx;
+  }
+
+  (wantarray) ? %rec : \%rec;
+}
+
+1;
+
-- 
GitLab