package Psh::Joblist; use strict; require Psh::OS; my @jobs_order=(); my %jobs_list=(); sub create_job { my ($pid, $call, $assoc_obj) = @_; my $job = new Psh::Job( $pid, $call, $assoc_obj); $jobs_list{$pid}=$job; push(@jobs_order,$job); return $job; } sub delete_job { my ($pid) = @_; my $job= $jobs_list{$pid}; return if !defined($job); delete $jobs_list{$pid}; my $i; for($i=0; $i <= $#jobs_order; $i++) { last if( $jobs_order[$i]==$job); } splice( @jobs_order, $i, 1); } sub job_exists { my $pid= shift; return exists($jobs_list{$pid}); } sub get_job { my $pid= shift; return $jobs_list{$pid}; } sub list_jobs { return @jobs_order; } sub get_job_number { my $pid= shift; for( my $i=0; $i<=$#jobs_order; $i++) { return $i+1 if( $jobs_order[$i]->{pid}==$pid); } return -1; } # # $pid=Psh::Joblist::find_job([$jobnumber]) # Finds either the job with the specified job number # or the highest numbered not running job and returns # the job or undef is none is found # sub find_job { my $job_to_start= shift; return $jobs_order[$job_to_start] if defined( $job_to_start); for (my $i = $#jobs_order; $i >= 0; $i--) { my $job = $jobs_order[$i]; if(!$job->{running}) { return wantarray?($i,$job):$job; } } return undef; } sub find_last_with_name { my ($name, $runningflag) = @_; enumerate(); my $index=0; while( my $job= Psh::Joblist::each()) { next if $runningflag && $job->{running}; my $call= $job->{call}; if ($call=~ m:([^/\s]+)\s*: ) { $call= $1; } elsif( $call=~ m:/([^/\s]+)\s+.*$: ) { $call= $1; } elsif ( $call=~ m:^([^/\s]+): ) { $call= $1; } if( $call eq $name) { return wantarray?($index,$job->{pid},$job->{call}):$index; } $index++; } return wantarray?():undef; } { my $pointer; # # Resets the enumeration counter for access using "each" # sub enumerate { $pointer=0; } # # Returns the next job # sub each { if ($pointer <= $#jobs_order) { return $jobs_order[$pointer++]; } return undef; } } package Psh::Job; # # $job= new Psh::Job( pid, call); # Creates a new Job object # pid is the pid of the object # call is the name of the executed command # sub new { my ( $class, $pid, $call, $assoc_obj ) = @_; my $self = {}; bless $self, $class; $self->{pid}=$pid; $self->{call}=$call; $self->{running}=1; $self->{assoc_obj}=$assoc_obj; return $self; } # # $job->run; # Sends SIGCONT to the job and records it running # sub continue { my $self= shift; # minus sign to wake up the whole group of the child: if( Psh::OS::has_job_control()) { Psh::OS::resume_job($self); } $self->{running}=1; } 1; __END__ =head1 NAME Psh::Joblist - A data structure suitable for handling job lists like bash's =head1 SYNOPSIS use Psh::Joblist; $job = Psh::Joblist::create_job($pid,$displayed_command); Psh::Joblist::delete_job($pid); $job = Psh::Joblist::get_job($pid); $flag = Psh::Joblist::job_exists($pid); $index = Psh::Joblist::get_job_number($pid); $job = Psh::Joblist::find_job(); $job = Psh::Joblist::find_job($index); Psh::Joblist::enumerate(); while( $job= Psh::Joblist::each()) { ... } =head1 DESCRIPTION Read the source ;-) =head1 AUTHOR Markus Peter (warp@spin.de) =cut