1       #!/usr/bin/perl -Tw
2       use strict;
3	$|++;
4
5	use CGI qw(:all);
6	use HTML::Table;
7
8	my $sortcol = param('sortcol');
9	unless (defined $sortcol and $sortcol =~ /\A-?\d+\z/) {
10	  $sortcol = 0;
11	}
12
13	print header, start_html("Processes");
14
15	$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
16	my @result = map {
17	  [map /\s*(\S.*\S|\S?)/, 
18	   unpack "A8 x1 A5 x1 A4 x1 A4 x1 A5 x1 A5 x1 A3 x1 A4 x0 A6 x1 A6 x1 A*", $_] 
19	      } `ps uaxww`; 20
21	## first generate the table by generating the header...
22
23	my $table = HTML::Table->new;
24	for ((my @headers = @{shift @result}),
25	     (my $col = 0);
26	     $col <= $#headers;
27	     $col++) {
28	  my $tag = $col + 1;
29	  my $icon = "";
30	  if ($tag == $sortcol) {
31	    $icon = img({src => "/icons/down.gif"});
32	    $tag = -$tag;
33	  } elsif (-$tag == $sortcol) {
34	    $icon = img({src => "/icons/up.gif"});
35	    $tag = -$tag;
36	  }
37	  $table->addCol($icon .
38	                 a({href => script_name()."?sortcol=$tag"},
39	                   escapeHTML($headers[$col])));
40	}
41	$table->setRowHead(1);
42
43	## at this point, we need to sort the data based on $sortcol, which is 1-based 
44
45	if ($sortcol) {
46	  my $alpha = 0;
47	  my $direction = $sortcol <=> 0; # -1 or +1
48	  my $column = abs($sortcol) - 1; # 0-based now
49
50	  ## detect the need for an alpha sort, if column contains non-numeric data
51	  for (@result) {
52	    $alpha = 1, last if $_->[$column] =~ /[^\-\d.]/;
53	  }
54
55	  if ($alpha) {
56	    @result = sort { $direction * ($a->[$column] cmp $b->[$column])} @result; 
57	  } else {
58	    @result = sort { $direction * ($a->[$column] <=> $b->[$column])} @result;
59	  }
60	}
61
62	## and finally add the sorted data to the table, checking for spanning...
63
64	my @previous;
65	my @previous_row_number;
66
67	for (@result) {
68	  my @this_row = @$_;
69	  my $this_row_number = $table->addRow(map escapeHTML($_),
70	                                       @this_row); # undocumented return value
71	  for my $col (0..$#this_row) {
72	    if (defined $previous[$col] and $previous[$col] eq $this_row[$col]) {
73	      ## we have a span
74	      my $previous_row_number = $previous_row_number[$col];
75	      $table->setCellRowSpan($previous_row_number, 1 + $col,
76	                             $this_row_number - $previous_row_number + 1);
77	    } else {
78	      $previous[$col] = $this_row[$col];
79	      $previous_row_number[$col] = $this_row_number;
80	    }
81	  }
82	}
83
84	$table->setBorder(2);
85	$table->setCellSpacing(0);
86	$table->setCellPadding(2);
87	print "$table";
88
89	print end_html;