#!/usr/local/bin/perl5
#
# A mod_perl CGI script for managing printer queues, get the status from the
# printer and put the jobs into a scrolling list or cancel one or more jobs
# that a user has selected.
#
#

use IO::Socket;
use CGI qw(:html2 :html3 start_form end_form center textfield textarea submit
           defaults scrolling_list hidden param);
use CGI::Carp qw(fatalsToBrowser);
use Apache::Constants qw(:response);

########################################################################
#
# Get the printer status.
#
# Returns an array of responses gleaned from the host.
#

sub get_status
{
  my $print_host = shift(@_);
  my $printer = shift(@_);
  my @response;

  my $lpd_socket = IO::Socket::INET->new(PeerAddr => $print_host,
                                         PeerPort => 'printer',
                                         Proto    => 'tcp')
    || die "Cannot open Socket to $print_host\n";

  print $lpd_socket "\003$printer \n"; # lpd magic to get short queue status
  while (<$lpd_socket>)
  {
    next unless ((m/^active/) || (m/^[0-9]+/));
    push(@response, $_);
  }

  return @response;
}

########################################################################
#
# Cancel the given jobs on the specified printer and print host.
#
#
sub cancel_job
{
  my $print_host = shift(@_);
  my $printer = shift(@_);
  my $jobs = join(" ", @_);
  my $result;

  my $lpd_socket = IO::Socket::INET->new(PeerAddr => $print_host,
                                         PeerPort => 'printer',
                                         Proto    => 'tcp')
    || die "Cannot open Socket to $print_host\n";

  print $lpd_socket "\005$printer root $jobs\n";

  $result = <$lpd_socket>;

  return ($result ne "");
}

########################################################################
#
# Main line.
#
my $r = Apache->request;
my $job, @jobs, $printer, $print_host, @ids, $rank, $userid, $jobid, $stuff;
my $plural;

$r->content_type('text/html');
$r->send_http_header;

CGI::import_names('PARAMS');

#
# Grab the printer name and host from the URL first off.
#
$print_host = $PARAMS::print_host;
$printer = $PARAMS::printer;

$r->print(start_html(-bgcolor => 'white', -Title => 'Printer Management'));
$r->print(start_form());

#
# Then hide the print host and printer names for refresh and deletes.
#
$r->print(hidden(-name => 'hidden_print_host', -default => "$print_host"));
$r->print(hidden(-name => 'hidden_printer', -default => "$printer"));

my $button = param('Delete');
my $refresh = param('Refresh');

#
# If the refresh button is hit then believe the hidden fields for the page.
#
if (($refresh eq 'Refresh') || ($button eq 'Delete'))
{
  $print_host = param('hidden_print_host');
  $printer = param('hidden_printer');
}

$r->print(h1("Printer Management For Printer $printer On $print_host"));

if (($refresh eq 'Refresh') || ($button ne 'Delete'))
{
  my @jobs = &get_status($print_host, $printer);

  if ($jobs[0] eq "")
  {
    $r->print(h1("No Jobs On The Print Queue"));
  }
  else
  {
    # print the printer status
    $r->print(br, scrolling_list(-name => 'job_list',
                                 -values => [@jobs],
                                 -size => 10,
                                 -multiple => 'true'));
    
    $r->print(p,p, submit(-name=>'Delete', -value => 'Delete'));
  }
}
elsif ($button eq 'Delete')
{
  @jobs = param('job_list');

  undef @ids;

  foreach $job (@jobs)
  {
    ($rank, $userid, $jobid, $stuff) = split(" ", $job);
    $r->print("Cancelling Job Id $jobid<br>\n");
    push(@ids, $jobid);
  }

  if ($ids[0] eq "")
  {
    $r->print(h1('No Jobs Selected To Be Cancelled'), br);
  }
  else
  {
    $plural = "";
    $plural = "s" if ($#ids > 0);

    if (cancel_job($print_host, $printer, @ids))
    {
      $r->print(h1("Selected Job$plural Cancelled"), br);
    }
    else
    {
      $r->print(h1("Failed To Cancel Selected Job$plural"));
    }
  }
}

$r->print(submit(-name=>'Refresh', -value => 'Refresh'));
$r->print(end_form(), end_html());

